191b4e487SEugen Hristev // SPDX-License-Identifier: GPL-2.0-only 291b4e487SEugen Hristev /* 391b4e487SEugen Hristev * Microchip Image Sensor Controller (ISC) common driver base 491b4e487SEugen Hristev * 591b4e487SEugen Hristev * Copyright (C) 2016-2019 Microchip Technology, Inc. 691b4e487SEugen Hristev * 791b4e487SEugen Hristev * Author: Songjun Wu 891b4e487SEugen Hristev * Author: Eugen Hristev <eugen.hristev@microchip.com> 991b4e487SEugen Hristev * 1091b4e487SEugen Hristev */ 1191b4e487SEugen Hristev #include <linux/delay.h> 1291b4e487SEugen Hristev #include <linux/interrupt.h> 1391b4e487SEugen Hristev #include <linux/math64.h> 1491b4e487SEugen Hristev #include <linux/module.h> 1591b4e487SEugen Hristev #include <linux/of.h> 1691b4e487SEugen Hristev #include <linux/of_graph.h> 1791b4e487SEugen Hristev #include <linux/platform_device.h> 1891b4e487SEugen Hristev #include <linux/pm_runtime.h> 1991b4e487SEugen Hristev #include <linux/regmap.h> 2091b4e487SEugen Hristev #include <linux/videodev2.h> 2191b4e487SEugen Hristev #include <linux/atmel-isc-media.h> 2291b4e487SEugen Hristev 2391b4e487SEugen Hristev #include <media/v4l2-ctrls.h> 2491b4e487SEugen Hristev #include <media/v4l2-device.h> 2591b4e487SEugen Hristev #include <media/v4l2-event.h> 2691b4e487SEugen Hristev #include <media/v4l2-image-sizes.h> 2791b4e487SEugen Hristev #include <media/v4l2-ioctl.h> 2891b4e487SEugen Hristev #include <media/v4l2-fwnode.h> 2991b4e487SEugen Hristev #include <media/v4l2-subdev.h> 3091b4e487SEugen Hristev #include <media/videobuf2-dma-contig.h> 3191b4e487SEugen Hristev 3291b4e487SEugen Hristev #include "microchip-isc-regs.h" 3391b4e487SEugen Hristev #include "microchip-isc.h" 3491b4e487SEugen Hristev 3591b4e487SEugen Hristev static unsigned int debug; 3691b4e487SEugen Hristev module_param(debug, int, 0644); 3791b4e487SEugen Hristev MODULE_PARM_DESC(debug, "debug level (0-2)"); 3891b4e487SEugen Hristev 3991b4e487SEugen Hristev static unsigned int sensor_preferred = 1; 4091b4e487SEugen Hristev module_param(sensor_preferred, uint, 0644); 4191b4e487SEugen Hristev MODULE_PARM_DESC(sensor_preferred, 4291b4e487SEugen Hristev "Sensor is preferred to output the specified format (1-on 0-off), default 1"); 4391b4e487SEugen Hristev 4491b4e487SEugen Hristev #define ISC_IS_FORMAT_RAW(mbus_code) \ 4591b4e487SEugen Hristev (((mbus_code) & 0xf000) == 0x3000) 4691b4e487SEugen Hristev 4791b4e487SEugen Hristev #define ISC_IS_FORMAT_GREY(mbus_code) \ 4891b4e487SEugen Hristev (((mbus_code) == MEDIA_BUS_FMT_Y10_1X10) | \ 4991b4e487SEugen Hristev (((mbus_code) == MEDIA_BUS_FMT_Y8_1X8))) 5091b4e487SEugen Hristev 5191b4e487SEugen Hristev static inline void isc_update_v4l2_ctrls(struct isc_device *isc) 5291b4e487SEugen Hristev { 5391b4e487SEugen Hristev struct isc_ctrls *ctrls = &isc->ctrls; 5491b4e487SEugen Hristev 5591b4e487SEugen Hristev /* In here we set the v4l2 controls w.r.t. our pipeline config */ 5691b4e487SEugen Hristev v4l2_ctrl_s_ctrl(isc->r_gain_ctrl, ctrls->gain[ISC_HIS_CFG_MODE_R]); 5791b4e487SEugen Hristev v4l2_ctrl_s_ctrl(isc->b_gain_ctrl, ctrls->gain[ISC_HIS_CFG_MODE_B]); 5891b4e487SEugen Hristev v4l2_ctrl_s_ctrl(isc->gr_gain_ctrl, ctrls->gain[ISC_HIS_CFG_MODE_GR]); 5991b4e487SEugen Hristev v4l2_ctrl_s_ctrl(isc->gb_gain_ctrl, ctrls->gain[ISC_HIS_CFG_MODE_GB]); 6091b4e487SEugen Hristev 6191b4e487SEugen Hristev v4l2_ctrl_s_ctrl(isc->r_off_ctrl, ctrls->offset[ISC_HIS_CFG_MODE_R]); 6291b4e487SEugen Hristev v4l2_ctrl_s_ctrl(isc->b_off_ctrl, ctrls->offset[ISC_HIS_CFG_MODE_B]); 6391b4e487SEugen Hristev v4l2_ctrl_s_ctrl(isc->gr_off_ctrl, ctrls->offset[ISC_HIS_CFG_MODE_GR]); 6491b4e487SEugen Hristev v4l2_ctrl_s_ctrl(isc->gb_off_ctrl, ctrls->offset[ISC_HIS_CFG_MODE_GB]); 6591b4e487SEugen Hristev } 6691b4e487SEugen Hristev 6791b4e487SEugen Hristev static inline void isc_update_awb_ctrls(struct isc_device *isc) 6891b4e487SEugen Hristev { 6991b4e487SEugen Hristev struct isc_ctrls *ctrls = &isc->ctrls; 7091b4e487SEugen Hristev 7191b4e487SEugen Hristev /* In here we set our actual hw pipeline config */ 7291b4e487SEugen Hristev 7391b4e487SEugen Hristev regmap_write(isc->regmap, ISC_WB_O_RGR, 7491b4e487SEugen Hristev ((ctrls->offset[ISC_HIS_CFG_MODE_R])) | 7591b4e487SEugen Hristev ((ctrls->offset[ISC_HIS_CFG_MODE_GR]) << 16)); 7691b4e487SEugen Hristev regmap_write(isc->regmap, ISC_WB_O_BGB, 7791b4e487SEugen Hristev ((ctrls->offset[ISC_HIS_CFG_MODE_B])) | 7891b4e487SEugen Hristev ((ctrls->offset[ISC_HIS_CFG_MODE_GB]) << 16)); 7991b4e487SEugen Hristev regmap_write(isc->regmap, ISC_WB_G_RGR, 8091b4e487SEugen Hristev ctrls->gain[ISC_HIS_CFG_MODE_R] | 8191b4e487SEugen Hristev (ctrls->gain[ISC_HIS_CFG_MODE_GR] << 16)); 8291b4e487SEugen Hristev regmap_write(isc->regmap, ISC_WB_G_BGB, 8391b4e487SEugen Hristev ctrls->gain[ISC_HIS_CFG_MODE_B] | 8491b4e487SEugen Hristev (ctrls->gain[ISC_HIS_CFG_MODE_GB] << 16)); 8591b4e487SEugen Hristev } 8691b4e487SEugen Hristev 8791b4e487SEugen Hristev static inline void isc_reset_awb_ctrls(struct isc_device *isc) 8891b4e487SEugen Hristev { 8991b4e487SEugen Hristev unsigned int c; 9091b4e487SEugen Hristev 9191b4e487SEugen Hristev for (c = ISC_HIS_CFG_MODE_GR; c <= ISC_HIS_CFG_MODE_B; c++) { 9291b4e487SEugen Hristev /* gains have a fixed point at 9 decimals */ 9391b4e487SEugen Hristev isc->ctrls.gain[c] = 1 << 9; 9491b4e487SEugen Hristev /* offsets are in 2's complements */ 9591b4e487SEugen Hristev isc->ctrls.offset[c] = 0; 9691b4e487SEugen Hristev } 9791b4e487SEugen Hristev } 9891b4e487SEugen Hristev 9991b4e487SEugen Hristev static int isc_queue_setup(struct vb2_queue *vq, 10091b4e487SEugen Hristev unsigned int *nbuffers, unsigned int *nplanes, 10191b4e487SEugen Hristev unsigned int sizes[], struct device *alloc_devs[]) 10291b4e487SEugen Hristev { 10391b4e487SEugen Hristev struct isc_device *isc = vb2_get_drv_priv(vq); 10491b4e487SEugen Hristev unsigned int size = isc->fmt.fmt.pix.sizeimage; 10591b4e487SEugen Hristev 10691b4e487SEugen Hristev if (*nplanes) 10791b4e487SEugen Hristev return sizes[0] < size ? -EINVAL : 0; 10891b4e487SEugen Hristev 10991b4e487SEugen Hristev *nplanes = 1; 11091b4e487SEugen Hristev sizes[0] = size; 11191b4e487SEugen Hristev 11291b4e487SEugen Hristev return 0; 11391b4e487SEugen Hristev } 11491b4e487SEugen Hristev 11591b4e487SEugen Hristev static int isc_buffer_prepare(struct vb2_buffer *vb) 11691b4e487SEugen Hristev { 11791b4e487SEugen Hristev struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 11891b4e487SEugen Hristev struct isc_device *isc = vb2_get_drv_priv(vb->vb2_queue); 11991b4e487SEugen Hristev unsigned long size = isc->fmt.fmt.pix.sizeimage; 12091b4e487SEugen Hristev 12191b4e487SEugen Hristev if (vb2_plane_size(vb, 0) < size) { 12291b4e487SEugen Hristev v4l2_err(&isc->v4l2_dev, "buffer too small (%lu < %lu)\n", 12391b4e487SEugen Hristev vb2_plane_size(vb, 0), size); 12491b4e487SEugen Hristev return -EINVAL; 12591b4e487SEugen Hristev } 12691b4e487SEugen Hristev 12791b4e487SEugen Hristev vb2_set_plane_payload(vb, 0, size); 12891b4e487SEugen Hristev 12991b4e487SEugen Hristev vbuf->field = isc->fmt.fmt.pix.field; 13091b4e487SEugen Hristev 13191b4e487SEugen Hristev return 0; 13291b4e487SEugen Hristev } 13391b4e487SEugen Hristev 13491b4e487SEugen Hristev static void isc_crop_pfe(struct isc_device *isc) 13591b4e487SEugen Hristev { 13691b4e487SEugen Hristev struct regmap *regmap = isc->regmap; 13791b4e487SEugen Hristev u32 h, w; 13891b4e487SEugen Hristev 13991b4e487SEugen Hristev h = isc->fmt.fmt.pix.height; 14091b4e487SEugen Hristev w = isc->fmt.fmt.pix.width; 14191b4e487SEugen Hristev 14291b4e487SEugen Hristev /* 14391b4e487SEugen Hristev * In case the sensor is not RAW, it will output a pixel (12-16 bits) 14491b4e487SEugen Hristev * with two samples on the ISC Data bus (which is 8-12) 14591b4e487SEugen Hristev * ISC will count each sample, so, we need to multiply these values 14691b4e487SEugen Hristev * by two, to get the real number of samples for the required pixels. 14791b4e487SEugen Hristev */ 14891b4e487SEugen Hristev if (!ISC_IS_FORMAT_RAW(isc->config.sd_format->mbus_code)) { 14991b4e487SEugen Hristev h <<= 1; 15091b4e487SEugen Hristev w <<= 1; 15191b4e487SEugen Hristev } 15291b4e487SEugen Hristev 15391b4e487SEugen Hristev /* 15491b4e487SEugen Hristev * We limit the column/row count that the ISC will output according 15591b4e487SEugen Hristev * to the configured resolution that we want. 15691b4e487SEugen Hristev * This will avoid the situation where the sensor is misconfigured, 15791b4e487SEugen Hristev * sending more data, and the ISC will just take it and DMA to memory, 15891b4e487SEugen Hristev * causing corruption. 15991b4e487SEugen Hristev */ 16091b4e487SEugen Hristev regmap_write(regmap, ISC_PFE_CFG1, 16191b4e487SEugen Hristev (ISC_PFE_CFG1_COLMIN(0) & ISC_PFE_CFG1_COLMIN_MASK) | 16291b4e487SEugen Hristev (ISC_PFE_CFG1_COLMAX(w - 1) & ISC_PFE_CFG1_COLMAX_MASK)); 16391b4e487SEugen Hristev 16491b4e487SEugen Hristev regmap_write(regmap, ISC_PFE_CFG2, 16591b4e487SEugen Hristev (ISC_PFE_CFG2_ROWMIN(0) & ISC_PFE_CFG2_ROWMIN_MASK) | 16691b4e487SEugen Hristev (ISC_PFE_CFG2_ROWMAX(h - 1) & ISC_PFE_CFG2_ROWMAX_MASK)); 16791b4e487SEugen Hristev 16891b4e487SEugen Hristev regmap_update_bits(regmap, ISC_PFE_CFG0, 16991b4e487SEugen Hristev ISC_PFE_CFG0_COLEN | ISC_PFE_CFG0_ROWEN, 17091b4e487SEugen Hristev ISC_PFE_CFG0_COLEN | ISC_PFE_CFG0_ROWEN); 17191b4e487SEugen Hristev } 17291b4e487SEugen Hristev 17391b4e487SEugen Hristev static void isc_start_dma(struct isc_device *isc) 17491b4e487SEugen Hristev { 17591b4e487SEugen Hristev struct regmap *regmap = isc->regmap; 17691b4e487SEugen Hristev u32 sizeimage = isc->fmt.fmt.pix.sizeimage; 17791b4e487SEugen Hristev u32 dctrl_dview; 17891b4e487SEugen Hristev dma_addr_t addr0; 17991b4e487SEugen Hristev 18091b4e487SEugen Hristev addr0 = vb2_dma_contig_plane_dma_addr(&isc->cur_frm->vb.vb2_buf, 0); 18191b4e487SEugen Hristev regmap_write(regmap, ISC_DAD0 + isc->offsets.dma, addr0); 18291b4e487SEugen Hristev 18391b4e487SEugen Hristev switch (isc->config.fourcc) { 18491b4e487SEugen Hristev case V4L2_PIX_FMT_YUV420: 18591b4e487SEugen Hristev regmap_write(regmap, ISC_DAD1 + isc->offsets.dma, 18691b4e487SEugen Hristev addr0 + (sizeimage * 2) / 3); 18791b4e487SEugen Hristev regmap_write(regmap, ISC_DAD2 + isc->offsets.dma, 18891b4e487SEugen Hristev addr0 + (sizeimage * 5) / 6); 18991b4e487SEugen Hristev break; 19091b4e487SEugen Hristev case V4L2_PIX_FMT_YUV422P: 19191b4e487SEugen Hristev regmap_write(regmap, ISC_DAD1 + isc->offsets.dma, 19291b4e487SEugen Hristev addr0 + sizeimage / 2); 19391b4e487SEugen Hristev regmap_write(regmap, ISC_DAD2 + isc->offsets.dma, 19491b4e487SEugen Hristev addr0 + (sizeimage * 3) / 4); 19591b4e487SEugen Hristev break; 19691b4e487SEugen Hristev default: 19791b4e487SEugen Hristev break; 19891b4e487SEugen Hristev } 19991b4e487SEugen Hristev 20091b4e487SEugen Hristev dctrl_dview = isc->config.dctrl_dview; 20191b4e487SEugen Hristev 20291b4e487SEugen Hristev regmap_write(regmap, ISC_DCTRL + isc->offsets.dma, 20391b4e487SEugen Hristev dctrl_dview | ISC_DCTRL_IE_IS); 20491b4e487SEugen Hristev spin_lock(&isc->awb_lock); 20591b4e487SEugen Hristev regmap_write(regmap, ISC_CTRLEN, ISC_CTRL_CAPTURE); 20691b4e487SEugen Hristev spin_unlock(&isc->awb_lock); 20791b4e487SEugen Hristev } 20891b4e487SEugen Hristev 20991b4e487SEugen Hristev static void isc_set_pipeline(struct isc_device *isc, u32 pipeline) 21091b4e487SEugen Hristev { 21191b4e487SEugen Hristev struct regmap *regmap = isc->regmap; 21291b4e487SEugen Hristev struct isc_ctrls *ctrls = &isc->ctrls; 21391b4e487SEugen Hristev u32 val, bay_cfg; 21491b4e487SEugen Hristev const u32 *gamma; 21591b4e487SEugen Hristev unsigned int i; 21691b4e487SEugen Hristev 21791b4e487SEugen Hristev /* WB-->CFA-->CC-->GAM-->CSC-->CBC-->SUB422-->SUB420 */ 21891b4e487SEugen Hristev for (i = 0; i < ISC_PIPE_LINE_NODE_NUM; i++) { 21991b4e487SEugen Hristev val = pipeline & BIT(i) ? 1 : 0; 22091b4e487SEugen Hristev regmap_field_write(isc->pipeline[i], val); 22191b4e487SEugen Hristev } 22291b4e487SEugen Hristev 22391b4e487SEugen Hristev if (!pipeline) 22491b4e487SEugen Hristev return; 22591b4e487SEugen Hristev 22691b4e487SEugen Hristev bay_cfg = isc->config.sd_format->cfa_baycfg; 22791b4e487SEugen Hristev 22891b4e487SEugen Hristev regmap_write(regmap, ISC_WB_CFG, bay_cfg); 22991b4e487SEugen Hristev isc_update_awb_ctrls(isc); 23091b4e487SEugen Hristev isc_update_v4l2_ctrls(isc); 23191b4e487SEugen Hristev 23291b4e487SEugen Hristev regmap_write(regmap, ISC_CFA_CFG, bay_cfg | ISC_CFA_CFG_EITPOL); 23391b4e487SEugen Hristev 23491b4e487SEugen Hristev gamma = &isc->gamma_table[ctrls->gamma_index][0]; 23591b4e487SEugen Hristev regmap_bulk_write(regmap, ISC_GAM_BENTRY, gamma, GAMMA_ENTRIES); 23691b4e487SEugen Hristev regmap_bulk_write(regmap, ISC_GAM_GENTRY, gamma, GAMMA_ENTRIES); 23791b4e487SEugen Hristev regmap_bulk_write(regmap, ISC_GAM_RENTRY, gamma, GAMMA_ENTRIES); 23891b4e487SEugen Hristev 23991b4e487SEugen Hristev isc->config_dpc(isc); 24091b4e487SEugen Hristev isc->config_csc(isc); 24191b4e487SEugen Hristev isc->config_cbc(isc); 24291b4e487SEugen Hristev isc->config_cc(isc); 24391b4e487SEugen Hristev isc->config_gam(isc); 24491b4e487SEugen Hristev } 24591b4e487SEugen Hristev 24691b4e487SEugen Hristev static int isc_update_profile(struct isc_device *isc) 24791b4e487SEugen Hristev { 24891b4e487SEugen Hristev struct regmap *regmap = isc->regmap; 24991b4e487SEugen Hristev u32 sr; 25091b4e487SEugen Hristev int counter = 100; 25191b4e487SEugen Hristev 25291b4e487SEugen Hristev regmap_write(regmap, ISC_CTRLEN, ISC_CTRL_UPPRO); 25391b4e487SEugen Hristev 25491b4e487SEugen Hristev regmap_read(regmap, ISC_CTRLSR, &sr); 25591b4e487SEugen Hristev while ((sr & ISC_CTRL_UPPRO) && counter--) { 25691b4e487SEugen Hristev usleep_range(1000, 2000); 25791b4e487SEugen Hristev regmap_read(regmap, ISC_CTRLSR, &sr); 25891b4e487SEugen Hristev } 25991b4e487SEugen Hristev 26091b4e487SEugen Hristev if (counter < 0) { 26191b4e487SEugen Hristev v4l2_warn(&isc->v4l2_dev, "Time out to update profile\n"); 26291b4e487SEugen Hristev return -ETIMEDOUT; 26391b4e487SEugen Hristev } 26491b4e487SEugen Hristev 26591b4e487SEugen Hristev return 0; 26691b4e487SEugen Hristev } 26791b4e487SEugen Hristev 26891b4e487SEugen Hristev static void isc_set_histogram(struct isc_device *isc, bool enable) 26991b4e487SEugen Hristev { 27091b4e487SEugen Hristev struct regmap *regmap = isc->regmap; 27191b4e487SEugen Hristev struct isc_ctrls *ctrls = &isc->ctrls; 27291b4e487SEugen Hristev 27391b4e487SEugen Hristev if (enable) { 27491b4e487SEugen Hristev regmap_write(regmap, ISC_HIS_CFG + isc->offsets.his, 27591b4e487SEugen Hristev ISC_HIS_CFG_MODE_GR | 27691b4e487SEugen Hristev (isc->config.sd_format->cfa_baycfg 27791b4e487SEugen Hristev << ISC_HIS_CFG_BAYSEL_SHIFT) | 27891b4e487SEugen Hristev ISC_HIS_CFG_RAR); 27991b4e487SEugen Hristev regmap_write(regmap, ISC_HIS_CTRL + isc->offsets.his, 28091b4e487SEugen Hristev ISC_HIS_CTRL_EN); 28191b4e487SEugen Hristev regmap_write(regmap, ISC_INTEN, ISC_INT_HISDONE); 28291b4e487SEugen Hristev ctrls->hist_id = ISC_HIS_CFG_MODE_GR; 28391b4e487SEugen Hristev isc_update_profile(isc); 28491b4e487SEugen Hristev regmap_write(regmap, ISC_CTRLEN, ISC_CTRL_HISREQ); 28591b4e487SEugen Hristev 28691b4e487SEugen Hristev ctrls->hist_stat = HIST_ENABLED; 28791b4e487SEugen Hristev } else { 28891b4e487SEugen Hristev regmap_write(regmap, ISC_INTDIS, ISC_INT_HISDONE); 28991b4e487SEugen Hristev regmap_write(regmap, ISC_HIS_CTRL + isc->offsets.his, 29091b4e487SEugen Hristev ISC_HIS_CTRL_DIS); 29191b4e487SEugen Hristev 29291b4e487SEugen Hristev ctrls->hist_stat = HIST_DISABLED; 29391b4e487SEugen Hristev } 29491b4e487SEugen Hristev } 29591b4e487SEugen Hristev 29691b4e487SEugen Hristev static int isc_configure(struct isc_device *isc) 29791b4e487SEugen Hristev { 29891b4e487SEugen Hristev struct regmap *regmap = isc->regmap; 29991b4e487SEugen Hristev u32 pfe_cfg0, dcfg, mask, pipeline; 30091b4e487SEugen Hristev struct isc_subdev_entity *subdev = isc->current_subdev; 30191b4e487SEugen Hristev 30291b4e487SEugen Hristev pfe_cfg0 = isc->config.sd_format->pfe_cfg0_bps; 30391b4e487SEugen Hristev pipeline = isc->config.bits_pipeline; 30491b4e487SEugen Hristev 30591b4e487SEugen Hristev dcfg = isc->config.dcfg_imode | isc->dcfg; 30691b4e487SEugen Hristev 30791b4e487SEugen Hristev pfe_cfg0 |= subdev->pfe_cfg0 | ISC_PFE_CFG0_MODE_PROGRESSIVE; 30891b4e487SEugen Hristev mask = ISC_PFE_CFG0_BPS_MASK | ISC_PFE_CFG0_HPOL_LOW | 30991b4e487SEugen Hristev ISC_PFE_CFG0_VPOL_LOW | ISC_PFE_CFG0_PPOL_LOW | 31091b4e487SEugen Hristev ISC_PFE_CFG0_MODE_MASK | ISC_PFE_CFG0_CCIR_CRC | 31191b4e487SEugen Hristev ISC_PFE_CFG0_CCIR656 | ISC_PFE_CFG0_MIPI; 31291b4e487SEugen Hristev 31391b4e487SEugen Hristev regmap_update_bits(regmap, ISC_PFE_CFG0, mask, pfe_cfg0); 31491b4e487SEugen Hristev 31591b4e487SEugen Hristev isc->config_rlp(isc); 31691b4e487SEugen Hristev 31791b4e487SEugen Hristev regmap_write(regmap, ISC_DCFG + isc->offsets.dma, dcfg); 31891b4e487SEugen Hristev 31991b4e487SEugen Hristev /* Set the pipeline */ 32091b4e487SEugen Hristev isc_set_pipeline(isc, pipeline); 32191b4e487SEugen Hristev 32291b4e487SEugen Hristev /* 32391b4e487SEugen Hristev * The current implemented histogram is available for RAW R, B, GB, GR 32491b4e487SEugen Hristev * channels. We need to check if sensor is outputting RAW BAYER 32591b4e487SEugen Hristev */ 32691b4e487SEugen Hristev if (isc->ctrls.awb && 32791b4e487SEugen Hristev ISC_IS_FORMAT_RAW(isc->config.sd_format->mbus_code)) 32891b4e487SEugen Hristev isc_set_histogram(isc, true); 32991b4e487SEugen Hristev else 33091b4e487SEugen Hristev isc_set_histogram(isc, false); 33191b4e487SEugen Hristev 33291b4e487SEugen Hristev /* Update profile */ 33391b4e487SEugen Hristev return isc_update_profile(isc); 33491b4e487SEugen Hristev } 33591b4e487SEugen Hristev 33691b4e487SEugen Hristev static int isc_start_streaming(struct vb2_queue *vq, unsigned int count) 33791b4e487SEugen Hristev { 33891b4e487SEugen Hristev struct isc_device *isc = vb2_get_drv_priv(vq); 33991b4e487SEugen Hristev struct regmap *regmap = isc->regmap; 34091b4e487SEugen Hristev struct isc_buffer *buf; 34191b4e487SEugen Hristev unsigned long flags; 34291b4e487SEugen Hristev int ret; 34391b4e487SEugen Hristev 34491b4e487SEugen Hristev /* Enable stream on the sub device */ 34591b4e487SEugen Hristev ret = v4l2_subdev_call(isc->current_subdev->sd, video, s_stream, 1); 34691b4e487SEugen Hristev if (ret && ret != -ENOIOCTLCMD) { 34791b4e487SEugen Hristev v4l2_err(&isc->v4l2_dev, "stream on failed in subdev %d\n", 34891b4e487SEugen Hristev ret); 34991b4e487SEugen Hristev goto err_start_stream; 35091b4e487SEugen Hristev } 35191b4e487SEugen Hristev 35291b4e487SEugen Hristev ret = pm_runtime_resume_and_get(isc->dev); 35391b4e487SEugen Hristev if (ret < 0) { 35491b4e487SEugen Hristev v4l2_err(&isc->v4l2_dev, "RPM resume failed in subdev %d\n", 35591b4e487SEugen Hristev ret); 35691b4e487SEugen Hristev goto err_pm_get; 35791b4e487SEugen Hristev } 35891b4e487SEugen Hristev 35991b4e487SEugen Hristev ret = isc_configure(isc); 36091b4e487SEugen Hristev if (unlikely(ret)) 36191b4e487SEugen Hristev goto err_configure; 36291b4e487SEugen Hristev 36391b4e487SEugen Hristev /* Enable DMA interrupt */ 36491b4e487SEugen Hristev regmap_write(regmap, ISC_INTEN, ISC_INT_DDONE); 36591b4e487SEugen Hristev 36691b4e487SEugen Hristev spin_lock_irqsave(&isc->dma_queue_lock, flags); 36791b4e487SEugen Hristev 36891b4e487SEugen Hristev isc->sequence = 0; 36991b4e487SEugen Hristev isc->stop = false; 37091b4e487SEugen Hristev reinit_completion(&isc->comp); 37191b4e487SEugen Hristev 37291b4e487SEugen Hristev isc->cur_frm = list_first_entry(&isc->dma_queue, 37391b4e487SEugen Hristev struct isc_buffer, list); 37491b4e487SEugen Hristev list_del(&isc->cur_frm->list); 37591b4e487SEugen Hristev 37691b4e487SEugen Hristev isc_crop_pfe(isc); 37791b4e487SEugen Hristev isc_start_dma(isc); 37891b4e487SEugen Hristev 37991b4e487SEugen Hristev spin_unlock_irqrestore(&isc->dma_queue_lock, flags); 38091b4e487SEugen Hristev 38191b4e487SEugen Hristev /* if we streaming from RAW, we can do one-shot white balance adj */ 38291b4e487SEugen Hristev if (ISC_IS_FORMAT_RAW(isc->config.sd_format->mbus_code)) 38391b4e487SEugen Hristev v4l2_ctrl_activate(isc->do_wb_ctrl, true); 38491b4e487SEugen Hristev 38591b4e487SEugen Hristev return 0; 38691b4e487SEugen Hristev 38791b4e487SEugen Hristev err_configure: 38891b4e487SEugen Hristev pm_runtime_put_sync(isc->dev); 38991b4e487SEugen Hristev err_pm_get: 39091b4e487SEugen Hristev v4l2_subdev_call(isc->current_subdev->sd, video, s_stream, 0); 39191b4e487SEugen Hristev 39291b4e487SEugen Hristev err_start_stream: 39391b4e487SEugen Hristev spin_lock_irqsave(&isc->dma_queue_lock, flags); 39491b4e487SEugen Hristev list_for_each_entry(buf, &isc->dma_queue, list) 39591b4e487SEugen Hristev vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED); 39691b4e487SEugen Hristev INIT_LIST_HEAD(&isc->dma_queue); 39791b4e487SEugen Hristev spin_unlock_irqrestore(&isc->dma_queue_lock, flags); 39891b4e487SEugen Hristev 39991b4e487SEugen Hristev return ret; 40091b4e487SEugen Hristev } 40191b4e487SEugen Hristev 40291b4e487SEugen Hristev static void isc_stop_streaming(struct vb2_queue *vq) 40391b4e487SEugen Hristev { 40491b4e487SEugen Hristev struct isc_device *isc = vb2_get_drv_priv(vq); 40591b4e487SEugen Hristev unsigned long flags; 40691b4e487SEugen Hristev struct isc_buffer *buf; 40791b4e487SEugen Hristev int ret; 40891b4e487SEugen Hristev 40991b4e487SEugen Hristev mutex_lock(&isc->awb_mutex); 41091b4e487SEugen Hristev v4l2_ctrl_activate(isc->do_wb_ctrl, false); 41191b4e487SEugen Hristev 41291b4e487SEugen Hristev isc->stop = true; 41391b4e487SEugen Hristev 41491b4e487SEugen Hristev /* Wait until the end of the current frame */ 41591b4e487SEugen Hristev if (isc->cur_frm && !wait_for_completion_timeout(&isc->comp, 5 * HZ)) 41691b4e487SEugen Hristev v4l2_err(&isc->v4l2_dev, 41791b4e487SEugen Hristev "Timeout waiting for end of the capture\n"); 41891b4e487SEugen Hristev 41991b4e487SEugen Hristev mutex_unlock(&isc->awb_mutex); 42091b4e487SEugen Hristev 42191b4e487SEugen Hristev /* Disable DMA interrupt */ 42291b4e487SEugen Hristev regmap_write(isc->regmap, ISC_INTDIS, ISC_INT_DDONE); 42391b4e487SEugen Hristev 42491b4e487SEugen Hristev pm_runtime_put_sync(isc->dev); 42591b4e487SEugen Hristev 42691b4e487SEugen Hristev /* Disable stream on the sub device */ 42791b4e487SEugen Hristev ret = v4l2_subdev_call(isc->current_subdev->sd, video, s_stream, 0); 42891b4e487SEugen Hristev if (ret && ret != -ENOIOCTLCMD) 42991b4e487SEugen Hristev v4l2_err(&isc->v4l2_dev, "stream off failed in subdev\n"); 43091b4e487SEugen Hristev 43191b4e487SEugen Hristev /* Release all active buffers */ 43291b4e487SEugen Hristev spin_lock_irqsave(&isc->dma_queue_lock, flags); 43391b4e487SEugen Hristev if (unlikely(isc->cur_frm)) { 43491b4e487SEugen Hristev vb2_buffer_done(&isc->cur_frm->vb.vb2_buf, 43591b4e487SEugen Hristev VB2_BUF_STATE_ERROR); 43691b4e487SEugen Hristev isc->cur_frm = NULL; 43791b4e487SEugen Hristev } 43891b4e487SEugen Hristev list_for_each_entry(buf, &isc->dma_queue, list) 43991b4e487SEugen Hristev vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); 44091b4e487SEugen Hristev INIT_LIST_HEAD(&isc->dma_queue); 44191b4e487SEugen Hristev spin_unlock_irqrestore(&isc->dma_queue_lock, flags); 44291b4e487SEugen Hristev } 44391b4e487SEugen Hristev 44491b4e487SEugen Hristev static void isc_buffer_queue(struct vb2_buffer *vb) 44591b4e487SEugen Hristev { 44691b4e487SEugen Hristev struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 44791b4e487SEugen Hristev struct isc_buffer *buf = container_of(vbuf, struct isc_buffer, vb); 44891b4e487SEugen Hristev struct isc_device *isc = vb2_get_drv_priv(vb->vb2_queue); 44991b4e487SEugen Hristev unsigned long flags; 45091b4e487SEugen Hristev 45191b4e487SEugen Hristev spin_lock_irqsave(&isc->dma_queue_lock, flags); 45291b4e487SEugen Hristev if (!isc->cur_frm && list_empty(&isc->dma_queue) && 45391b4e487SEugen Hristev vb2_start_streaming_called(vb->vb2_queue)) { 45491b4e487SEugen Hristev isc->cur_frm = buf; 45591b4e487SEugen Hristev isc_start_dma(isc); 45691b4e487SEugen Hristev } else { 45791b4e487SEugen Hristev list_add_tail(&buf->list, &isc->dma_queue); 45891b4e487SEugen Hristev } 45991b4e487SEugen Hristev spin_unlock_irqrestore(&isc->dma_queue_lock, flags); 46091b4e487SEugen Hristev } 46191b4e487SEugen Hristev 46291b4e487SEugen Hristev static struct isc_format *find_format_by_fourcc(struct isc_device *isc, 46391b4e487SEugen Hristev unsigned int fourcc) 46491b4e487SEugen Hristev { 46591b4e487SEugen Hristev unsigned int num_formats = isc->num_user_formats; 46691b4e487SEugen Hristev struct isc_format *fmt; 46791b4e487SEugen Hristev unsigned int i; 46891b4e487SEugen Hristev 46991b4e487SEugen Hristev for (i = 0; i < num_formats; i++) { 47091b4e487SEugen Hristev fmt = isc->user_formats[i]; 47191b4e487SEugen Hristev if (fmt->fourcc == fourcc) 47291b4e487SEugen Hristev return fmt; 47391b4e487SEugen Hristev } 47491b4e487SEugen Hristev 47591b4e487SEugen Hristev return NULL; 47691b4e487SEugen Hristev } 47791b4e487SEugen Hristev 47891b4e487SEugen Hristev static const struct vb2_ops isc_vb2_ops = { 47991b4e487SEugen Hristev .queue_setup = isc_queue_setup, 48091b4e487SEugen Hristev .wait_prepare = vb2_ops_wait_prepare, 48191b4e487SEugen Hristev .wait_finish = vb2_ops_wait_finish, 48291b4e487SEugen Hristev .buf_prepare = isc_buffer_prepare, 48391b4e487SEugen Hristev .start_streaming = isc_start_streaming, 48491b4e487SEugen Hristev .stop_streaming = isc_stop_streaming, 48591b4e487SEugen Hristev .buf_queue = isc_buffer_queue, 48691b4e487SEugen Hristev }; 48791b4e487SEugen Hristev 48891b4e487SEugen Hristev static int isc_querycap(struct file *file, void *priv, 48991b4e487SEugen Hristev struct v4l2_capability *cap) 49091b4e487SEugen Hristev { 49191b4e487SEugen Hristev struct isc_device *isc = video_drvdata(file); 49291b4e487SEugen Hristev 49391b4e487SEugen Hristev strscpy(cap->driver, "microchip-isc", sizeof(cap->driver)); 49491b4e487SEugen Hristev strscpy(cap->card, "Microchip Image Sensor Controller", sizeof(cap->card)); 49591b4e487SEugen Hristev snprintf(cap->bus_info, sizeof(cap->bus_info), 49691b4e487SEugen Hristev "platform:%s", isc->v4l2_dev.name); 49791b4e487SEugen Hristev 49891b4e487SEugen Hristev return 0; 49991b4e487SEugen Hristev } 50091b4e487SEugen Hristev 50191b4e487SEugen Hristev static int isc_enum_fmt_vid_cap(struct file *file, void *priv, 50291b4e487SEugen Hristev struct v4l2_fmtdesc *f) 50391b4e487SEugen Hristev { 50491b4e487SEugen Hristev struct isc_device *isc = video_drvdata(file); 50591b4e487SEugen Hristev u32 index = f->index; 50691b4e487SEugen Hristev u32 i, supported_index; 50791b4e487SEugen Hristev 50891b4e487SEugen Hristev if (index < isc->controller_formats_size) { 50991b4e487SEugen Hristev f->pixelformat = isc->controller_formats[index].fourcc; 51091b4e487SEugen Hristev return 0; 51191b4e487SEugen Hristev } 51291b4e487SEugen Hristev 51391b4e487SEugen Hristev index -= isc->controller_formats_size; 51491b4e487SEugen Hristev 51591b4e487SEugen Hristev supported_index = 0; 51691b4e487SEugen Hristev 51791b4e487SEugen Hristev for (i = 0; i < isc->formats_list_size; i++) { 51891b4e487SEugen Hristev if (!ISC_IS_FORMAT_RAW(isc->formats_list[i].mbus_code) || 51991b4e487SEugen Hristev !isc->formats_list[i].sd_support) 52091b4e487SEugen Hristev continue; 52191b4e487SEugen Hristev if (supported_index == index) { 52291b4e487SEugen Hristev f->pixelformat = isc->formats_list[i].fourcc; 52391b4e487SEugen Hristev return 0; 52491b4e487SEugen Hristev } 52591b4e487SEugen Hristev supported_index++; 52691b4e487SEugen Hristev } 52791b4e487SEugen Hristev 52891b4e487SEugen Hristev return -EINVAL; 52991b4e487SEugen Hristev } 53091b4e487SEugen Hristev 53191b4e487SEugen Hristev static int isc_g_fmt_vid_cap(struct file *file, void *priv, 53291b4e487SEugen Hristev struct v4l2_format *fmt) 53391b4e487SEugen Hristev { 53491b4e487SEugen Hristev struct isc_device *isc = video_drvdata(file); 53591b4e487SEugen Hristev 53691b4e487SEugen Hristev *fmt = isc->fmt; 53791b4e487SEugen Hristev 53891b4e487SEugen Hristev return 0; 53991b4e487SEugen Hristev } 54091b4e487SEugen Hristev 54191b4e487SEugen Hristev /* 54291b4e487SEugen Hristev * Checks the current configured format, if ISC can output it, 54391b4e487SEugen Hristev * considering which type of format the ISC receives from the sensor 54491b4e487SEugen Hristev */ 54591b4e487SEugen Hristev static int isc_try_validate_formats(struct isc_device *isc) 54691b4e487SEugen Hristev { 54791b4e487SEugen Hristev int ret; 54891b4e487SEugen Hristev bool bayer = false, yuv = false, rgb = false, grey = false; 54991b4e487SEugen Hristev 55091b4e487SEugen Hristev /* all formats supported by the RLP module are OK */ 55191b4e487SEugen Hristev switch (isc->try_config.fourcc) { 55291b4e487SEugen Hristev case V4L2_PIX_FMT_SBGGR8: 55391b4e487SEugen Hristev case V4L2_PIX_FMT_SGBRG8: 55491b4e487SEugen Hristev case V4L2_PIX_FMT_SGRBG8: 55591b4e487SEugen Hristev case V4L2_PIX_FMT_SRGGB8: 55691b4e487SEugen Hristev case V4L2_PIX_FMT_SBGGR10: 55791b4e487SEugen Hristev case V4L2_PIX_FMT_SGBRG10: 55891b4e487SEugen Hristev case V4L2_PIX_FMT_SGRBG10: 55991b4e487SEugen Hristev case V4L2_PIX_FMT_SRGGB10: 56091b4e487SEugen Hristev case V4L2_PIX_FMT_SBGGR12: 56191b4e487SEugen Hristev case V4L2_PIX_FMT_SGBRG12: 56291b4e487SEugen Hristev case V4L2_PIX_FMT_SGRBG12: 56391b4e487SEugen Hristev case V4L2_PIX_FMT_SRGGB12: 56491b4e487SEugen Hristev ret = 0; 56591b4e487SEugen Hristev bayer = true; 56691b4e487SEugen Hristev break; 56791b4e487SEugen Hristev 56891b4e487SEugen Hristev case V4L2_PIX_FMT_YUV420: 56991b4e487SEugen Hristev case V4L2_PIX_FMT_YUV422P: 57091b4e487SEugen Hristev case V4L2_PIX_FMT_YUYV: 57191b4e487SEugen Hristev case V4L2_PIX_FMT_UYVY: 57291b4e487SEugen Hristev case V4L2_PIX_FMT_VYUY: 57391b4e487SEugen Hristev ret = 0; 57491b4e487SEugen Hristev yuv = true; 57591b4e487SEugen Hristev break; 57691b4e487SEugen Hristev 57791b4e487SEugen Hristev case V4L2_PIX_FMT_RGB565: 57891b4e487SEugen Hristev case V4L2_PIX_FMT_ABGR32: 57991b4e487SEugen Hristev case V4L2_PIX_FMT_XBGR32: 58091b4e487SEugen Hristev case V4L2_PIX_FMT_ARGB444: 58191b4e487SEugen Hristev case V4L2_PIX_FMT_ARGB555: 58291b4e487SEugen Hristev ret = 0; 58391b4e487SEugen Hristev rgb = true; 58491b4e487SEugen Hristev break; 58591b4e487SEugen Hristev case V4L2_PIX_FMT_GREY: 58691b4e487SEugen Hristev case V4L2_PIX_FMT_Y10: 58791b4e487SEugen Hristev case V4L2_PIX_FMT_Y16: 58891b4e487SEugen Hristev ret = 0; 58991b4e487SEugen Hristev grey = true; 59091b4e487SEugen Hristev break; 59191b4e487SEugen Hristev default: 59291b4e487SEugen Hristev /* any other different formats are not supported */ 59391b4e487SEugen Hristev ret = -EINVAL; 59491b4e487SEugen Hristev } 59591b4e487SEugen Hristev v4l2_dbg(1, debug, &isc->v4l2_dev, 59691b4e487SEugen Hristev "Format validation, requested rgb=%u, yuv=%u, grey=%u, bayer=%u\n", 59791b4e487SEugen Hristev rgb, yuv, grey, bayer); 59891b4e487SEugen Hristev 59991b4e487SEugen Hristev /* we cannot output RAW if we do not receive RAW */ 60091b4e487SEugen Hristev if ((bayer) && !ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code)) 60191b4e487SEugen Hristev return -EINVAL; 60291b4e487SEugen Hristev 60391b4e487SEugen Hristev /* we cannot output GREY if we do not receive RAW/GREY */ 60491b4e487SEugen Hristev if (grey && !ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code) && 60591b4e487SEugen Hristev !ISC_IS_FORMAT_GREY(isc->try_config.sd_format->mbus_code)) 60691b4e487SEugen Hristev return -EINVAL; 60791b4e487SEugen Hristev 60891b4e487SEugen Hristev return ret; 60991b4e487SEugen Hristev } 61091b4e487SEugen Hristev 61191b4e487SEugen Hristev /* 61291b4e487SEugen Hristev * Configures the RLP and DMA modules, depending on the output format 61391b4e487SEugen Hristev * configured for the ISC. 61491b4e487SEugen Hristev * If direct_dump == true, just dump raw data 8/16 bits depending on format. 61591b4e487SEugen Hristev */ 61691b4e487SEugen Hristev static int isc_try_configure_rlp_dma(struct isc_device *isc, bool direct_dump) 61791b4e487SEugen Hristev { 61891b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = 0; 61991b4e487SEugen Hristev 62091b4e487SEugen Hristev switch (isc->try_config.fourcc) { 62191b4e487SEugen Hristev case V4L2_PIX_FMT_SBGGR8: 62291b4e487SEugen Hristev case V4L2_PIX_FMT_SGBRG8: 62391b4e487SEugen Hristev case V4L2_PIX_FMT_SGRBG8: 62491b4e487SEugen Hristev case V4L2_PIX_FMT_SRGGB8: 62591b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT8; 62691b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED8; 62791b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; 62891b4e487SEugen Hristev isc->try_config.bpp = 8; 62991b4e487SEugen Hristev isc->try_config.bpp_v4l2 = 8; 63091b4e487SEugen Hristev break; 63191b4e487SEugen Hristev case V4L2_PIX_FMT_SBGGR10: 63291b4e487SEugen Hristev case V4L2_PIX_FMT_SGBRG10: 63391b4e487SEugen Hristev case V4L2_PIX_FMT_SGRBG10: 63491b4e487SEugen Hristev case V4L2_PIX_FMT_SRGGB10: 63591b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT10; 63691b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED16; 63791b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; 63891b4e487SEugen Hristev isc->try_config.bpp = 16; 63991b4e487SEugen Hristev isc->try_config.bpp_v4l2 = 16; 64091b4e487SEugen Hristev break; 64191b4e487SEugen Hristev case V4L2_PIX_FMT_SBGGR12: 64291b4e487SEugen Hristev case V4L2_PIX_FMT_SGBRG12: 64391b4e487SEugen Hristev case V4L2_PIX_FMT_SGRBG12: 64491b4e487SEugen Hristev case V4L2_PIX_FMT_SRGGB12: 64591b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT12; 64691b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED16; 64791b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; 64891b4e487SEugen Hristev isc->try_config.bpp = 16; 64991b4e487SEugen Hristev isc->try_config.bpp_v4l2 = 16; 65091b4e487SEugen Hristev break; 65191b4e487SEugen Hristev case V4L2_PIX_FMT_RGB565: 65291b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_RGB565; 65391b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED16; 65491b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; 65591b4e487SEugen Hristev isc->try_config.bpp = 16; 65691b4e487SEugen Hristev isc->try_config.bpp_v4l2 = 16; 65791b4e487SEugen Hristev break; 65891b4e487SEugen Hristev case V4L2_PIX_FMT_ARGB444: 65991b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_ARGB444; 66091b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED16; 66191b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; 66291b4e487SEugen Hristev isc->try_config.bpp = 16; 66391b4e487SEugen Hristev isc->try_config.bpp_v4l2 = 16; 66491b4e487SEugen Hristev break; 66591b4e487SEugen Hristev case V4L2_PIX_FMT_ARGB555: 66691b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_ARGB555; 66791b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED16; 66891b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; 66991b4e487SEugen Hristev isc->try_config.bpp = 16; 67091b4e487SEugen Hristev isc->try_config.bpp_v4l2 = 16; 67191b4e487SEugen Hristev break; 67291b4e487SEugen Hristev case V4L2_PIX_FMT_ABGR32: 67391b4e487SEugen Hristev case V4L2_PIX_FMT_XBGR32: 67491b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_ARGB32; 67591b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED32; 67691b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; 67791b4e487SEugen Hristev isc->try_config.bpp = 32; 67891b4e487SEugen Hristev isc->try_config.bpp_v4l2 = 32; 67991b4e487SEugen Hristev break; 68091b4e487SEugen Hristev case V4L2_PIX_FMT_YUV420: 68191b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_YYCC; 68291b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_YC420P; 68391b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PLANAR; 68491b4e487SEugen Hristev isc->try_config.bpp = 12; 68591b4e487SEugen Hristev isc->try_config.bpp_v4l2 = 8; /* only first plane */ 68691b4e487SEugen Hristev break; 68791b4e487SEugen Hristev case V4L2_PIX_FMT_YUV422P: 68891b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_YYCC; 68991b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_YC422P; 69091b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PLANAR; 69191b4e487SEugen Hristev isc->try_config.bpp = 16; 69291b4e487SEugen Hristev isc->try_config.bpp_v4l2 = 8; /* only first plane */ 69391b4e487SEugen Hristev break; 69491b4e487SEugen Hristev case V4L2_PIX_FMT_YUYV: 69591b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_YCYC | ISC_RLP_CFG_YMODE_YUYV; 69691b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED32; 69791b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; 69891b4e487SEugen Hristev isc->try_config.bpp = 16; 69991b4e487SEugen Hristev isc->try_config.bpp_v4l2 = 16; 70091b4e487SEugen Hristev break; 70191b4e487SEugen Hristev case V4L2_PIX_FMT_UYVY: 70291b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_YCYC | ISC_RLP_CFG_YMODE_UYVY; 70391b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED32; 70491b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; 70591b4e487SEugen Hristev isc->try_config.bpp = 16; 70691b4e487SEugen Hristev isc->try_config.bpp_v4l2 = 16; 70791b4e487SEugen Hristev break; 70891b4e487SEugen Hristev case V4L2_PIX_FMT_VYUY: 70991b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_YCYC | ISC_RLP_CFG_YMODE_VYUY; 71091b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED32; 71191b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; 71291b4e487SEugen Hristev isc->try_config.bpp = 16; 71391b4e487SEugen Hristev isc->try_config.bpp_v4l2 = 16; 71491b4e487SEugen Hristev break; 71591b4e487SEugen Hristev case V4L2_PIX_FMT_GREY: 71691b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_DATY8; 71791b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED8; 71891b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; 71991b4e487SEugen Hristev isc->try_config.bpp = 8; 72091b4e487SEugen Hristev isc->try_config.bpp_v4l2 = 8; 72191b4e487SEugen Hristev break; 72291b4e487SEugen Hristev case V4L2_PIX_FMT_Y16: 72391b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_DATY10 | ISC_RLP_CFG_LSH; 72491b4e487SEugen Hristev fallthrough; 72591b4e487SEugen Hristev case V4L2_PIX_FMT_Y10: 72691b4e487SEugen Hristev isc->try_config.rlp_cfg_mode |= ISC_RLP_CFG_MODE_DATY10; 72791b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED16; 72891b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; 72991b4e487SEugen Hristev isc->try_config.bpp = 16; 73091b4e487SEugen Hristev isc->try_config.bpp_v4l2 = 16; 73191b4e487SEugen Hristev break; 73291b4e487SEugen Hristev default: 73391b4e487SEugen Hristev return -EINVAL; 73491b4e487SEugen Hristev } 73591b4e487SEugen Hristev 73691b4e487SEugen Hristev if (direct_dump) { 73791b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT8; 73891b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED8; 73991b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; 74091b4e487SEugen Hristev return 0; 74191b4e487SEugen Hristev } 74291b4e487SEugen Hristev 74391b4e487SEugen Hristev return 0; 74491b4e487SEugen Hristev } 74591b4e487SEugen Hristev 74691b4e487SEugen Hristev /* 74791b4e487SEugen Hristev * Configuring pipeline modules, depending on which format the ISC outputs 74891b4e487SEugen Hristev * and considering which format it has as input from the sensor. 74991b4e487SEugen Hristev */ 75091b4e487SEugen Hristev static int isc_try_configure_pipeline(struct isc_device *isc) 75191b4e487SEugen Hristev { 75291b4e487SEugen Hristev switch (isc->try_config.fourcc) { 75391b4e487SEugen Hristev case V4L2_PIX_FMT_RGB565: 75491b4e487SEugen Hristev case V4L2_PIX_FMT_ARGB555: 75591b4e487SEugen Hristev case V4L2_PIX_FMT_ARGB444: 75691b4e487SEugen Hristev case V4L2_PIX_FMT_ABGR32: 75791b4e487SEugen Hristev case V4L2_PIX_FMT_XBGR32: 75891b4e487SEugen Hristev /* if sensor format is RAW, we convert inside ISC */ 75991b4e487SEugen Hristev if (ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code)) { 76091b4e487SEugen Hristev isc->try_config.bits_pipeline = CFA_ENABLE | 76191b4e487SEugen Hristev WB_ENABLE | GAM_ENABLES | DPC_BLCENABLE | 76291b4e487SEugen Hristev CC_ENABLE; 76391b4e487SEugen Hristev } else { 76491b4e487SEugen Hristev isc->try_config.bits_pipeline = 0x0; 76591b4e487SEugen Hristev } 76691b4e487SEugen Hristev break; 76791b4e487SEugen Hristev case V4L2_PIX_FMT_YUV420: 76891b4e487SEugen Hristev /* if sensor format is RAW, we convert inside ISC */ 76991b4e487SEugen Hristev if (ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code)) { 77091b4e487SEugen Hristev isc->try_config.bits_pipeline = CFA_ENABLE | 77191b4e487SEugen Hristev CSC_ENABLE | GAM_ENABLES | WB_ENABLE | 77291b4e487SEugen Hristev SUB420_ENABLE | SUB422_ENABLE | CBC_ENABLE | 77391b4e487SEugen Hristev DPC_BLCENABLE; 77491b4e487SEugen Hristev } else { 77591b4e487SEugen Hristev isc->try_config.bits_pipeline = 0x0; 77691b4e487SEugen Hristev } 77791b4e487SEugen Hristev break; 77891b4e487SEugen Hristev case V4L2_PIX_FMT_YUV422P: 77991b4e487SEugen Hristev /* if sensor format is RAW, we convert inside ISC */ 78091b4e487SEugen Hristev if (ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code)) { 78191b4e487SEugen Hristev isc->try_config.bits_pipeline = CFA_ENABLE | 78291b4e487SEugen Hristev CSC_ENABLE | WB_ENABLE | GAM_ENABLES | 78391b4e487SEugen Hristev SUB422_ENABLE | CBC_ENABLE | DPC_BLCENABLE; 78491b4e487SEugen Hristev } else { 78591b4e487SEugen Hristev isc->try_config.bits_pipeline = 0x0; 78691b4e487SEugen Hristev } 78791b4e487SEugen Hristev break; 78891b4e487SEugen Hristev case V4L2_PIX_FMT_YUYV: 78991b4e487SEugen Hristev case V4L2_PIX_FMT_UYVY: 79091b4e487SEugen Hristev case V4L2_PIX_FMT_VYUY: 79191b4e487SEugen Hristev /* if sensor format is RAW, we convert inside ISC */ 79291b4e487SEugen Hristev if (ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code)) { 79391b4e487SEugen Hristev isc->try_config.bits_pipeline = CFA_ENABLE | 79491b4e487SEugen Hristev CSC_ENABLE | WB_ENABLE | GAM_ENABLES | 79591b4e487SEugen Hristev SUB422_ENABLE | CBC_ENABLE | DPC_BLCENABLE; 79691b4e487SEugen Hristev } else { 79791b4e487SEugen Hristev isc->try_config.bits_pipeline = 0x0; 79891b4e487SEugen Hristev } 79991b4e487SEugen Hristev break; 80091b4e487SEugen Hristev case V4L2_PIX_FMT_GREY: 80191b4e487SEugen Hristev case V4L2_PIX_FMT_Y16: 80291b4e487SEugen Hristev /* if sensor format is RAW, we convert inside ISC */ 80391b4e487SEugen Hristev if (ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code)) { 80491b4e487SEugen Hristev isc->try_config.bits_pipeline = CFA_ENABLE | 80591b4e487SEugen Hristev CSC_ENABLE | WB_ENABLE | GAM_ENABLES | 80691b4e487SEugen Hristev CBC_ENABLE | DPC_BLCENABLE; 80791b4e487SEugen Hristev } else { 80891b4e487SEugen Hristev isc->try_config.bits_pipeline = 0x0; 80991b4e487SEugen Hristev } 81091b4e487SEugen Hristev break; 81191b4e487SEugen Hristev default: 81291b4e487SEugen Hristev if (ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code)) 81391b4e487SEugen Hristev isc->try_config.bits_pipeline = WB_ENABLE | DPC_BLCENABLE; 81491b4e487SEugen Hristev else 81591b4e487SEugen Hristev isc->try_config.bits_pipeline = 0x0; 81691b4e487SEugen Hristev } 81791b4e487SEugen Hristev 81891b4e487SEugen Hristev /* Tune the pipeline to product specific */ 81991b4e487SEugen Hristev isc->adapt_pipeline(isc); 82091b4e487SEugen Hristev 82191b4e487SEugen Hristev return 0; 82291b4e487SEugen Hristev } 82391b4e487SEugen Hristev 82491b4e487SEugen Hristev static void isc_try_fse(struct isc_device *isc, 82591b4e487SEugen Hristev struct v4l2_subdev_state *sd_state) 82691b4e487SEugen Hristev { 82791b4e487SEugen Hristev int ret; 82891b4e487SEugen Hristev struct v4l2_subdev_frame_size_enum fse = {}; 82991b4e487SEugen Hristev 83091b4e487SEugen Hristev /* 83191b4e487SEugen Hristev * If we do not know yet which format the subdev is using, we cannot 83291b4e487SEugen Hristev * do anything. 83391b4e487SEugen Hristev */ 83491b4e487SEugen Hristev if (!isc->try_config.sd_format) 83591b4e487SEugen Hristev return; 83691b4e487SEugen Hristev 83791b4e487SEugen Hristev fse.code = isc->try_config.sd_format->mbus_code; 83891b4e487SEugen Hristev fse.which = V4L2_SUBDEV_FORMAT_TRY; 83991b4e487SEugen Hristev 84091b4e487SEugen Hristev ret = v4l2_subdev_call(isc->current_subdev->sd, pad, enum_frame_size, 84191b4e487SEugen Hristev sd_state, &fse); 84291b4e487SEugen Hristev /* 84391b4e487SEugen Hristev * Attempt to obtain format size from subdev. If not available, 84491b4e487SEugen Hristev * just use the maximum ISC can receive. 84591b4e487SEugen Hristev */ 84691b4e487SEugen Hristev if (ret) { 84791b4e487SEugen Hristev sd_state->pads->try_crop.width = isc->max_width; 84891b4e487SEugen Hristev sd_state->pads->try_crop.height = isc->max_height; 84991b4e487SEugen Hristev } else { 85091b4e487SEugen Hristev sd_state->pads->try_crop.width = fse.max_width; 85191b4e487SEugen Hristev sd_state->pads->try_crop.height = fse.max_height; 85291b4e487SEugen Hristev } 85391b4e487SEugen Hristev } 85491b4e487SEugen Hristev 85591b4e487SEugen Hristev static int isc_try_fmt(struct isc_device *isc, struct v4l2_format *f, 85691b4e487SEugen Hristev u32 *code) 85791b4e487SEugen Hristev { 85891b4e487SEugen Hristev int i; 85991b4e487SEugen Hristev struct isc_format *sd_fmt = NULL, *direct_fmt = NULL; 86091b4e487SEugen Hristev struct v4l2_pix_format *pixfmt = &f->fmt.pix; 86191b4e487SEugen Hristev struct v4l2_subdev_pad_config pad_cfg = {}; 86291b4e487SEugen Hristev struct v4l2_subdev_state pad_state = { 86391b4e487SEugen Hristev .pads = &pad_cfg 86491b4e487SEugen Hristev }; 86591b4e487SEugen Hristev struct v4l2_subdev_format format = { 86691b4e487SEugen Hristev .which = V4L2_SUBDEV_FORMAT_TRY, 86791b4e487SEugen Hristev }; 86891b4e487SEugen Hristev u32 mbus_code; 86991b4e487SEugen Hristev int ret; 87091b4e487SEugen Hristev bool rlp_dma_direct_dump = false; 87191b4e487SEugen Hristev 87291b4e487SEugen Hristev if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 87391b4e487SEugen Hristev return -EINVAL; 87491b4e487SEugen Hristev 87591b4e487SEugen Hristev /* Step 1: find a RAW format that is supported */ 87691b4e487SEugen Hristev for (i = 0; i < isc->num_user_formats; i++) { 87791b4e487SEugen Hristev if (ISC_IS_FORMAT_RAW(isc->user_formats[i]->mbus_code)) { 87891b4e487SEugen Hristev sd_fmt = isc->user_formats[i]; 87991b4e487SEugen Hristev break; 88091b4e487SEugen Hristev } 88191b4e487SEugen Hristev } 88291b4e487SEugen Hristev /* Step 2: We can continue with this RAW format, or we can look 88391b4e487SEugen Hristev * for better: maybe sensor supports directly what we need. 88491b4e487SEugen Hristev */ 88591b4e487SEugen Hristev direct_fmt = find_format_by_fourcc(isc, pixfmt->pixelformat); 88691b4e487SEugen Hristev 88791b4e487SEugen Hristev /* Step 3: We have both. We decide given the module parameter which 88891b4e487SEugen Hristev * one to use. 88991b4e487SEugen Hristev */ 89091b4e487SEugen Hristev if (direct_fmt && sd_fmt && sensor_preferred) 89191b4e487SEugen Hristev sd_fmt = direct_fmt; 89291b4e487SEugen Hristev 89391b4e487SEugen Hristev /* Step 4: we do not have RAW but we have a direct format. Use it. */ 89491b4e487SEugen Hristev if (direct_fmt && !sd_fmt) 89591b4e487SEugen Hristev sd_fmt = direct_fmt; 89691b4e487SEugen Hristev 89791b4e487SEugen Hristev /* Step 5: if we are using a direct format, we need to package 89891b4e487SEugen Hristev * everything as 8 bit data and just dump it 89991b4e487SEugen Hristev */ 90091b4e487SEugen Hristev if (sd_fmt == direct_fmt) 90191b4e487SEugen Hristev rlp_dma_direct_dump = true; 90291b4e487SEugen Hristev 90391b4e487SEugen Hristev /* Step 6: We have no format. This can happen if the userspace 90491b4e487SEugen Hristev * requests some weird/invalid format. 90591b4e487SEugen Hristev * In this case, default to whatever we have 90691b4e487SEugen Hristev */ 90791b4e487SEugen Hristev if (!sd_fmt && !direct_fmt) { 90891b4e487SEugen Hristev sd_fmt = isc->user_formats[isc->num_user_formats - 1]; 90991b4e487SEugen Hristev v4l2_dbg(1, debug, &isc->v4l2_dev, 91091b4e487SEugen Hristev "Sensor not supporting %.4s, using %.4s\n", 91191b4e487SEugen Hristev (char *)&pixfmt->pixelformat, (char *)&sd_fmt->fourcc); 91291b4e487SEugen Hristev } 91391b4e487SEugen Hristev 91491b4e487SEugen Hristev if (!sd_fmt) { 91591b4e487SEugen Hristev ret = -EINVAL; 91691b4e487SEugen Hristev goto isc_try_fmt_err; 91791b4e487SEugen Hristev } 91891b4e487SEugen Hristev 91991b4e487SEugen Hristev /* Step 7: Print out what we decided for debugging */ 92091b4e487SEugen Hristev v4l2_dbg(1, debug, &isc->v4l2_dev, 92191b4e487SEugen Hristev "Preferring to have sensor using format %.4s\n", 92291b4e487SEugen Hristev (char *)&sd_fmt->fourcc); 92391b4e487SEugen Hristev 92491b4e487SEugen Hristev /* Step 8: at this moment we decided which format the subdev will use */ 92591b4e487SEugen Hristev isc->try_config.sd_format = sd_fmt; 92691b4e487SEugen Hristev 92791b4e487SEugen Hristev /* Limit to Microchip ISC hardware capabilities */ 92891b4e487SEugen Hristev if (pixfmt->width > isc->max_width) 92991b4e487SEugen Hristev pixfmt->width = isc->max_width; 93091b4e487SEugen Hristev if (pixfmt->height > isc->max_height) 93191b4e487SEugen Hristev pixfmt->height = isc->max_height; 93291b4e487SEugen Hristev 93391b4e487SEugen Hristev /* 93491b4e487SEugen Hristev * The mbus format is the one the subdev outputs. 93591b4e487SEugen Hristev * The pixels will be transferred in this format Sensor -> ISC 93691b4e487SEugen Hristev */ 93791b4e487SEugen Hristev mbus_code = sd_fmt->mbus_code; 93891b4e487SEugen Hristev 93991b4e487SEugen Hristev /* 94091b4e487SEugen Hristev * Validate formats. If the required format is not OK, default to raw. 94191b4e487SEugen Hristev */ 94291b4e487SEugen Hristev 94391b4e487SEugen Hristev isc->try_config.fourcc = pixfmt->pixelformat; 94491b4e487SEugen Hristev 94591b4e487SEugen Hristev if (isc_try_validate_formats(isc)) { 94691b4e487SEugen Hristev pixfmt->pixelformat = isc->try_config.fourcc = sd_fmt->fourcc; 94791b4e487SEugen Hristev /* Re-try to validate the new format */ 94891b4e487SEugen Hristev ret = isc_try_validate_formats(isc); 94991b4e487SEugen Hristev if (ret) 95091b4e487SEugen Hristev goto isc_try_fmt_err; 95191b4e487SEugen Hristev } 95291b4e487SEugen Hristev 95391b4e487SEugen Hristev ret = isc_try_configure_rlp_dma(isc, rlp_dma_direct_dump); 95491b4e487SEugen Hristev if (ret) 95591b4e487SEugen Hristev goto isc_try_fmt_err; 95691b4e487SEugen Hristev 95791b4e487SEugen Hristev ret = isc_try_configure_pipeline(isc); 95891b4e487SEugen Hristev if (ret) 95991b4e487SEugen Hristev goto isc_try_fmt_err; 96091b4e487SEugen Hristev 96191b4e487SEugen Hristev /* Obtain frame sizes if possible to have crop requirements ready */ 96291b4e487SEugen Hristev isc_try_fse(isc, &pad_state); 96391b4e487SEugen Hristev 96491b4e487SEugen Hristev v4l2_fill_mbus_format(&format.format, pixfmt, mbus_code); 96591b4e487SEugen Hristev ret = v4l2_subdev_call(isc->current_subdev->sd, pad, set_fmt, 96691b4e487SEugen Hristev &pad_state, &format); 96791b4e487SEugen Hristev if (ret < 0) 96891b4e487SEugen Hristev goto isc_try_fmt_subdev_err; 96991b4e487SEugen Hristev 97091b4e487SEugen Hristev v4l2_fill_pix_format(pixfmt, &format.format); 97191b4e487SEugen Hristev 97291b4e487SEugen Hristev /* Limit to Microchip ISC hardware capabilities */ 97391b4e487SEugen Hristev if (pixfmt->width > isc->max_width) 97491b4e487SEugen Hristev pixfmt->width = isc->max_width; 97591b4e487SEugen Hristev if (pixfmt->height > isc->max_height) 97691b4e487SEugen Hristev pixfmt->height = isc->max_height; 97791b4e487SEugen Hristev 97891b4e487SEugen Hristev pixfmt->field = V4L2_FIELD_NONE; 97991b4e487SEugen Hristev pixfmt->bytesperline = (pixfmt->width * isc->try_config.bpp_v4l2) >> 3; 98091b4e487SEugen Hristev pixfmt->sizeimage = ((pixfmt->width * isc->try_config.bpp) >> 3) * 98191b4e487SEugen Hristev pixfmt->height; 98291b4e487SEugen Hristev 98391b4e487SEugen Hristev if (code) 98491b4e487SEugen Hristev *code = mbus_code; 98591b4e487SEugen Hristev 98691b4e487SEugen Hristev return 0; 98791b4e487SEugen Hristev 98891b4e487SEugen Hristev isc_try_fmt_err: 98991b4e487SEugen Hristev v4l2_err(&isc->v4l2_dev, "Could not find any possible format for a working pipeline\n"); 99091b4e487SEugen Hristev isc_try_fmt_subdev_err: 99191b4e487SEugen Hristev memset(&isc->try_config, 0, sizeof(isc->try_config)); 99291b4e487SEugen Hristev 99391b4e487SEugen Hristev return ret; 99491b4e487SEugen Hristev } 99591b4e487SEugen Hristev 99691b4e487SEugen Hristev static int isc_set_fmt(struct isc_device *isc, struct v4l2_format *f) 99791b4e487SEugen Hristev { 99891b4e487SEugen Hristev struct v4l2_subdev_format format = { 99991b4e487SEugen Hristev .which = V4L2_SUBDEV_FORMAT_ACTIVE, 100091b4e487SEugen Hristev }; 100191b4e487SEugen Hristev u32 mbus_code = 0; 100291b4e487SEugen Hristev int ret; 100391b4e487SEugen Hristev 100491b4e487SEugen Hristev ret = isc_try_fmt(isc, f, &mbus_code); 100591b4e487SEugen Hristev if (ret) 100691b4e487SEugen Hristev return ret; 100791b4e487SEugen Hristev 100891b4e487SEugen Hristev v4l2_fill_mbus_format(&format.format, &f->fmt.pix, mbus_code); 100991b4e487SEugen Hristev ret = v4l2_subdev_call(isc->current_subdev->sd, pad, 101091b4e487SEugen Hristev set_fmt, NULL, &format); 101191b4e487SEugen Hristev if (ret < 0) 101291b4e487SEugen Hristev return ret; 101391b4e487SEugen Hristev 101491b4e487SEugen Hristev /* Limit to Microchip ISC hardware capabilities */ 101591b4e487SEugen Hristev if (f->fmt.pix.width > isc->max_width) 101691b4e487SEugen Hristev f->fmt.pix.width = isc->max_width; 101791b4e487SEugen Hristev if (f->fmt.pix.height > isc->max_height) 101891b4e487SEugen Hristev f->fmt.pix.height = isc->max_height; 101991b4e487SEugen Hristev 102091b4e487SEugen Hristev isc->fmt = *f; 102191b4e487SEugen Hristev 102291b4e487SEugen Hristev if (isc->try_config.sd_format && isc->config.sd_format && 102391b4e487SEugen Hristev isc->try_config.sd_format != isc->config.sd_format) { 102491b4e487SEugen Hristev isc->ctrls.hist_stat = HIST_INIT; 102591b4e487SEugen Hristev isc_reset_awb_ctrls(isc); 102691b4e487SEugen Hristev isc_update_v4l2_ctrls(isc); 102791b4e487SEugen Hristev } 102891b4e487SEugen Hristev /* make the try configuration active */ 102991b4e487SEugen Hristev isc->config = isc->try_config; 103091b4e487SEugen Hristev 103191b4e487SEugen Hristev v4l2_dbg(1, debug, &isc->v4l2_dev, "New ISC configuration in place\n"); 103291b4e487SEugen Hristev 103391b4e487SEugen Hristev return 0; 103491b4e487SEugen Hristev } 103591b4e487SEugen Hristev 103691b4e487SEugen Hristev static int isc_s_fmt_vid_cap(struct file *file, void *priv, 103791b4e487SEugen Hristev struct v4l2_format *f) 103891b4e487SEugen Hristev { 103991b4e487SEugen Hristev struct isc_device *isc = video_drvdata(file); 104091b4e487SEugen Hristev 104191b4e487SEugen Hristev if (vb2_is_busy(&isc->vb2_vidq)) 104291b4e487SEugen Hristev return -EBUSY; 104391b4e487SEugen Hristev 104491b4e487SEugen Hristev return isc_set_fmt(isc, f); 104591b4e487SEugen Hristev } 104691b4e487SEugen Hristev 104791b4e487SEugen Hristev static int isc_try_fmt_vid_cap(struct file *file, void *priv, 104891b4e487SEugen Hristev struct v4l2_format *f) 104991b4e487SEugen Hristev { 105091b4e487SEugen Hristev struct isc_device *isc = video_drvdata(file); 105191b4e487SEugen Hristev 105291b4e487SEugen Hristev return isc_try_fmt(isc, f, NULL); 105391b4e487SEugen Hristev } 105491b4e487SEugen Hristev 105591b4e487SEugen Hristev static int isc_enum_input(struct file *file, void *priv, 105691b4e487SEugen Hristev struct v4l2_input *inp) 105791b4e487SEugen Hristev { 105891b4e487SEugen Hristev if (inp->index != 0) 105991b4e487SEugen Hristev return -EINVAL; 106091b4e487SEugen Hristev 106191b4e487SEugen Hristev inp->type = V4L2_INPUT_TYPE_CAMERA; 106291b4e487SEugen Hristev inp->std = 0; 106391b4e487SEugen Hristev strscpy(inp->name, "Camera", sizeof(inp->name)); 106491b4e487SEugen Hristev 106591b4e487SEugen Hristev return 0; 106691b4e487SEugen Hristev } 106791b4e487SEugen Hristev 106891b4e487SEugen Hristev static int isc_g_input(struct file *file, void *priv, unsigned int *i) 106991b4e487SEugen Hristev { 107091b4e487SEugen Hristev *i = 0; 107191b4e487SEugen Hristev 107291b4e487SEugen Hristev return 0; 107391b4e487SEugen Hristev } 107491b4e487SEugen Hristev 107591b4e487SEugen Hristev static int isc_s_input(struct file *file, void *priv, unsigned int i) 107691b4e487SEugen Hristev { 107791b4e487SEugen Hristev if (i > 0) 107891b4e487SEugen Hristev return -EINVAL; 107991b4e487SEugen Hristev 108091b4e487SEugen Hristev return 0; 108191b4e487SEugen Hristev } 108291b4e487SEugen Hristev 108391b4e487SEugen Hristev static int isc_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a) 108491b4e487SEugen Hristev { 108591b4e487SEugen Hristev struct isc_device *isc = video_drvdata(file); 108691b4e487SEugen Hristev 108791b4e487SEugen Hristev return v4l2_g_parm_cap(video_devdata(file), isc->current_subdev->sd, a); 108891b4e487SEugen Hristev } 108991b4e487SEugen Hristev 109091b4e487SEugen Hristev static int isc_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a) 109191b4e487SEugen Hristev { 109291b4e487SEugen Hristev struct isc_device *isc = video_drvdata(file); 109391b4e487SEugen Hristev 109491b4e487SEugen Hristev return v4l2_s_parm_cap(video_devdata(file), isc->current_subdev->sd, a); 109591b4e487SEugen Hristev } 109691b4e487SEugen Hristev 109791b4e487SEugen Hristev static int isc_enum_framesizes(struct file *file, void *fh, 109891b4e487SEugen Hristev struct v4l2_frmsizeenum *fsize) 109991b4e487SEugen Hristev { 110091b4e487SEugen Hristev struct isc_device *isc = video_drvdata(file); 110191b4e487SEugen Hristev int ret = -EINVAL; 110291b4e487SEugen Hristev int i; 110391b4e487SEugen Hristev 110491b4e487SEugen Hristev if (fsize->index) 110591b4e487SEugen Hristev return -EINVAL; 110691b4e487SEugen Hristev 110791b4e487SEugen Hristev for (i = 0; i < isc->num_user_formats; i++) 110891b4e487SEugen Hristev if (isc->user_formats[i]->fourcc == fsize->pixel_format) 110991b4e487SEugen Hristev ret = 0; 111091b4e487SEugen Hristev 111191b4e487SEugen Hristev for (i = 0; i < isc->controller_formats_size; i++) 111291b4e487SEugen Hristev if (isc->controller_formats[i].fourcc == fsize->pixel_format) 111391b4e487SEugen Hristev ret = 0; 111491b4e487SEugen Hristev 111591b4e487SEugen Hristev if (ret) 111691b4e487SEugen Hristev return ret; 111791b4e487SEugen Hristev 111891b4e487SEugen Hristev fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS; 111991b4e487SEugen Hristev 112091b4e487SEugen Hristev fsize->stepwise.min_width = 16; 112191b4e487SEugen Hristev fsize->stepwise.max_width = isc->max_width; 112291b4e487SEugen Hristev fsize->stepwise.min_height = 16; 112391b4e487SEugen Hristev fsize->stepwise.max_height = isc->max_height; 112491b4e487SEugen Hristev fsize->stepwise.step_width = 1; 112591b4e487SEugen Hristev fsize->stepwise.step_height = 1; 112691b4e487SEugen Hristev 112791b4e487SEugen Hristev return 0; 112891b4e487SEugen Hristev } 112991b4e487SEugen Hristev 113091b4e487SEugen Hristev static const struct v4l2_ioctl_ops isc_ioctl_ops = { 113191b4e487SEugen Hristev .vidioc_querycap = isc_querycap, 113291b4e487SEugen Hristev .vidioc_enum_fmt_vid_cap = isc_enum_fmt_vid_cap, 113391b4e487SEugen Hristev .vidioc_g_fmt_vid_cap = isc_g_fmt_vid_cap, 113491b4e487SEugen Hristev .vidioc_s_fmt_vid_cap = isc_s_fmt_vid_cap, 113591b4e487SEugen Hristev .vidioc_try_fmt_vid_cap = isc_try_fmt_vid_cap, 113691b4e487SEugen Hristev 113791b4e487SEugen Hristev .vidioc_enum_input = isc_enum_input, 113891b4e487SEugen Hristev .vidioc_g_input = isc_g_input, 113991b4e487SEugen Hristev .vidioc_s_input = isc_s_input, 114091b4e487SEugen Hristev 114191b4e487SEugen Hristev .vidioc_reqbufs = vb2_ioctl_reqbufs, 114291b4e487SEugen Hristev .vidioc_querybuf = vb2_ioctl_querybuf, 114391b4e487SEugen Hristev .vidioc_qbuf = vb2_ioctl_qbuf, 114491b4e487SEugen Hristev .vidioc_expbuf = vb2_ioctl_expbuf, 114591b4e487SEugen Hristev .vidioc_dqbuf = vb2_ioctl_dqbuf, 114691b4e487SEugen Hristev .vidioc_create_bufs = vb2_ioctl_create_bufs, 114791b4e487SEugen Hristev .vidioc_prepare_buf = vb2_ioctl_prepare_buf, 114891b4e487SEugen Hristev .vidioc_streamon = vb2_ioctl_streamon, 114991b4e487SEugen Hristev .vidioc_streamoff = vb2_ioctl_streamoff, 115091b4e487SEugen Hristev 115191b4e487SEugen Hristev .vidioc_g_parm = isc_g_parm, 115291b4e487SEugen Hristev .vidioc_s_parm = isc_s_parm, 115391b4e487SEugen Hristev .vidioc_enum_framesizes = isc_enum_framesizes, 115491b4e487SEugen Hristev 115591b4e487SEugen Hristev .vidioc_log_status = v4l2_ctrl_log_status, 115691b4e487SEugen Hristev .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, 115791b4e487SEugen Hristev .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 115891b4e487SEugen Hristev }; 115991b4e487SEugen Hristev 116091b4e487SEugen Hristev static int isc_open(struct file *file) 116191b4e487SEugen Hristev { 116291b4e487SEugen Hristev struct isc_device *isc = video_drvdata(file); 116391b4e487SEugen Hristev struct v4l2_subdev *sd = isc->current_subdev->sd; 116491b4e487SEugen Hristev int ret; 116591b4e487SEugen Hristev 116691b4e487SEugen Hristev if (mutex_lock_interruptible(&isc->lock)) 116791b4e487SEugen Hristev return -ERESTARTSYS; 116891b4e487SEugen Hristev 116991b4e487SEugen Hristev ret = v4l2_fh_open(file); 117091b4e487SEugen Hristev if (ret < 0) 117191b4e487SEugen Hristev goto unlock; 117291b4e487SEugen Hristev 117391b4e487SEugen Hristev if (!v4l2_fh_is_singular_file(file)) 117491b4e487SEugen Hristev goto unlock; 117591b4e487SEugen Hristev 117691b4e487SEugen Hristev ret = v4l2_subdev_call(sd, core, s_power, 1); 117791b4e487SEugen Hristev if (ret < 0 && ret != -ENOIOCTLCMD) { 117891b4e487SEugen Hristev v4l2_fh_release(file); 117991b4e487SEugen Hristev goto unlock; 118091b4e487SEugen Hristev } 118191b4e487SEugen Hristev 118291b4e487SEugen Hristev ret = isc_set_fmt(isc, &isc->fmt); 118391b4e487SEugen Hristev if (ret) { 118491b4e487SEugen Hristev v4l2_subdev_call(sd, core, s_power, 0); 118591b4e487SEugen Hristev v4l2_fh_release(file); 118691b4e487SEugen Hristev } 118791b4e487SEugen Hristev 118891b4e487SEugen Hristev unlock: 118991b4e487SEugen Hristev mutex_unlock(&isc->lock); 119091b4e487SEugen Hristev return ret; 119191b4e487SEugen Hristev } 119291b4e487SEugen Hristev 119391b4e487SEugen Hristev static int isc_release(struct file *file) 119491b4e487SEugen Hristev { 119591b4e487SEugen Hristev struct isc_device *isc = video_drvdata(file); 119691b4e487SEugen Hristev struct v4l2_subdev *sd = isc->current_subdev->sd; 119791b4e487SEugen Hristev bool fh_singular; 119891b4e487SEugen Hristev int ret; 119991b4e487SEugen Hristev 120091b4e487SEugen Hristev mutex_lock(&isc->lock); 120191b4e487SEugen Hristev 120291b4e487SEugen Hristev fh_singular = v4l2_fh_is_singular_file(file); 120391b4e487SEugen Hristev 120491b4e487SEugen Hristev ret = _vb2_fop_release(file, NULL); 120591b4e487SEugen Hristev 120691b4e487SEugen Hristev if (fh_singular) 120791b4e487SEugen Hristev v4l2_subdev_call(sd, core, s_power, 0); 120891b4e487SEugen Hristev 120991b4e487SEugen Hristev mutex_unlock(&isc->lock); 121091b4e487SEugen Hristev 121191b4e487SEugen Hristev return ret; 121291b4e487SEugen Hristev } 121391b4e487SEugen Hristev 121491b4e487SEugen Hristev static const struct v4l2_file_operations isc_fops = { 121591b4e487SEugen Hristev .owner = THIS_MODULE, 121691b4e487SEugen Hristev .open = isc_open, 121791b4e487SEugen Hristev .release = isc_release, 121891b4e487SEugen Hristev .unlocked_ioctl = video_ioctl2, 121991b4e487SEugen Hristev .read = vb2_fop_read, 122091b4e487SEugen Hristev .mmap = vb2_fop_mmap, 122191b4e487SEugen Hristev .poll = vb2_fop_poll, 122291b4e487SEugen Hristev }; 122391b4e487SEugen Hristev 122491b4e487SEugen Hristev irqreturn_t microchip_isc_interrupt(int irq, void *dev_id) 122591b4e487SEugen Hristev { 122691b4e487SEugen Hristev struct isc_device *isc = (struct isc_device *)dev_id; 122791b4e487SEugen Hristev struct regmap *regmap = isc->regmap; 122891b4e487SEugen Hristev u32 isc_intsr, isc_intmask, pending; 122991b4e487SEugen Hristev irqreturn_t ret = IRQ_NONE; 123091b4e487SEugen Hristev 123191b4e487SEugen Hristev regmap_read(regmap, ISC_INTSR, &isc_intsr); 123291b4e487SEugen Hristev regmap_read(regmap, ISC_INTMASK, &isc_intmask); 123391b4e487SEugen Hristev 123491b4e487SEugen Hristev pending = isc_intsr & isc_intmask; 123591b4e487SEugen Hristev 123691b4e487SEugen Hristev if (likely(pending & ISC_INT_DDONE)) { 123791b4e487SEugen Hristev spin_lock(&isc->dma_queue_lock); 123891b4e487SEugen Hristev if (isc->cur_frm) { 123991b4e487SEugen Hristev struct vb2_v4l2_buffer *vbuf = &isc->cur_frm->vb; 124091b4e487SEugen Hristev struct vb2_buffer *vb = &vbuf->vb2_buf; 124191b4e487SEugen Hristev 124291b4e487SEugen Hristev vb->timestamp = ktime_get_ns(); 124391b4e487SEugen Hristev vbuf->sequence = isc->sequence++; 124491b4e487SEugen Hristev vb2_buffer_done(vb, VB2_BUF_STATE_DONE); 124591b4e487SEugen Hristev isc->cur_frm = NULL; 124691b4e487SEugen Hristev } 124791b4e487SEugen Hristev 124891b4e487SEugen Hristev if (!list_empty(&isc->dma_queue) && !isc->stop) { 124991b4e487SEugen Hristev isc->cur_frm = list_first_entry(&isc->dma_queue, 125091b4e487SEugen Hristev struct isc_buffer, list); 125191b4e487SEugen Hristev list_del(&isc->cur_frm->list); 125291b4e487SEugen Hristev 125391b4e487SEugen Hristev isc_start_dma(isc); 125491b4e487SEugen Hristev } 125591b4e487SEugen Hristev 125691b4e487SEugen Hristev if (isc->stop) 125791b4e487SEugen Hristev complete(&isc->comp); 125891b4e487SEugen Hristev 125991b4e487SEugen Hristev ret = IRQ_HANDLED; 126091b4e487SEugen Hristev spin_unlock(&isc->dma_queue_lock); 126191b4e487SEugen Hristev } 126291b4e487SEugen Hristev 126391b4e487SEugen Hristev if (pending & ISC_INT_HISDONE) { 126491b4e487SEugen Hristev schedule_work(&isc->awb_work); 126591b4e487SEugen Hristev ret = IRQ_HANDLED; 126691b4e487SEugen Hristev } 126791b4e487SEugen Hristev 126891b4e487SEugen Hristev return ret; 126991b4e487SEugen Hristev } 127091b4e487SEugen Hristev EXPORT_SYMBOL_GPL(microchip_isc_interrupt); 127191b4e487SEugen Hristev 127291b4e487SEugen Hristev static void isc_hist_count(struct isc_device *isc, u32 *min, u32 *max) 127391b4e487SEugen Hristev { 127491b4e487SEugen Hristev struct regmap *regmap = isc->regmap; 127591b4e487SEugen Hristev struct isc_ctrls *ctrls = &isc->ctrls; 127691b4e487SEugen Hristev u32 *hist_count = &ctrls->hist_count[ctrls->hist_id]; 127791b4e487SEugen Hristev u32 *hist_entry = &ctrls->hist_entry[0]; 127891b4e487SEugen Hristev u32 i; 127991b4e487SEugen Hristev 128091b4e487SEugen Hristev *min = 0; 128191b4e487SEugen Hristev *max = HIST_ENTRIES; 128291b4e487SEugen Hristev 128391b4e487SEugen Hristev regmap_bulk_read(regmap, ISC_HIS_ENTRY + isc->offsets.his_entry, 128491b4e487SEugen Hristev hist_entry, HIST_ENTRIES); 128591b4e487SEugen Hristev 128691b4e487SEugen Hristev *hist_count = 0; 128791b4e487SEugen Hristev /* 128891b4e487SEugen Hristev * we deliberately ignore the end of the histogram, 128991b4e487SEugen Hristev * the most white pixels 129091b4e487SEugen Hristev */ 129191b4e487SEugen Hristev for (i = 1; i < HIST_ENTRIES; i++) { 129291b4e487SEugen Hristev if (*hist_entry && !*min) 129391b4e487SEugen Hristev *min = i; 129491b4e487SEugen Hristev if (*hist_entry) 129591b4e487SEugen Hristev *max = i; 129691b4e487SEugen Hristev *hist_count += i * (*hist_entry++); 129791b4e487SEugen Hristev } 129891b4e487SEugen Hristev 129991b4e487SEugen Hristev if (!*min) 130091b4e487SEugen Hristev *min = 1; 130191b4e487SEugen Hristev 130291b4e487SEugen Hristev v4l2_dbg(1, debug, &isc->v4l2_dev, 130391b4e487SEugen Hristev "isc wb: hist_id %u, hist_count %u", 130491b4e487SEugen Hristev ctrls->hist_id, *hist_count); 130591b4e487SEugen Hristev } 130691b4e487SEugen Hristev 130791b4e487SEugen Hristev static void isc_wb_update(struct isc_ctrls *ctrls) 130891b4e487SEugen Hristev { 130991b4e487SEugen Hristev struct isc_device *isc = container_of(ctrls, struct isc_device, ctrls); 131091b4e487SEugen Hristev u32 *hist_count = &ctrls->hist_count[0]; 131191b4e487SEugen Hristev u32 c, offset[4]; 131291b4e487SEugen Hristev u64 avg = 0; 131391b4e487SEugen Hristev /* We compute two gains, stretch gain and grey world gain */ 131491b4e487SEugen Hristev u32 s_gain[4], gw_gain[4]; 131591b4e487SEugen Hristev 131691b4e487SEugen Hristev /* 131791b4e487SEugen Hristev * According to Grey World, we need to set gains for R/B to normalize 131891b4e487SEugen Hristev * them towards the green channel. 131991b4e487SEugen Hristev * Thus we want to keep Green as fixed and adjust only Red/Blue 132091b4e487SEugen Hristev * Compute the average of the both green channels first 132191b4e487SEugen Hristev */ 132291b4e487SEugen Hristev avg = (u64)hist_count[ISC_HIS_CFG_MODE_GR] + 132391b4e487SEugen Hristev (u64)hist_count[ISC_HIS_CFG_MODE_GB]; 132491b4e487SEugen Hristev avg >>= 1; 132591b4e487SEugen Hristev 132691b4e487SEugen Hristev v4l2_dbg(1, debug, &isc->v4l2_dev, 132791b4e487SEugen Hristev "isc wb: green components average %llu\n", avg); 132891b4e487SEugen Hristev 132991b4e487SEugen Hristev /* Green histogram is null, nothing to do */ 133091b4e487SEugen Hristev if (!avg) 133191b4e487SEugen Hristev return; 133291b4e487SEugen Hristev 133391b4e487SEugen Hristev for (c = ISC_HIS_CFG_MODE_GR; c <= ISC_HIS_CFG_MODE_B; c++) { 133491b4e487SEugen Hristev /* 133591b4e487SEugen Hristev * the color offset is the minimum value of the histogram. 133691b4e487SEugen Hristev * we stretch this color to the full range by substracting 133791b4e487SEugen Hristev * this value from the color component. 133891b4e487SEugen Hristev */ 133991b4e487SEugen Hristev offset[c] = ctrls->hist_minmax[c][HIST_MIN_INDEX]; 134091b4e487SEugen Hristev /* 134191b4e487SEugen Hristev * The offset is always at least 1. If the offset is 1, we do 134291b4e487SEugen Hristev * not need to adjust it, so our result must be zero. 134391b4e487SEugen Hristev * the offset is computed in a histogram on 9 bits (0..512) 134491b4e487SEugen Hristev * but the offset in register is based on 134591b4e487SEugen Hristev * 12 bits pipeline (0..4096). 134691b4e487SEugen Hristev * we need to shift with the 3 bits that the histogram is 134791b4e487SEugen Hristev * ignoring 134891b4e487SEugen Hristev */ 134991b4e487SEugen Hristev ctrls->offset[c] = (offset[c] - 1) << 3; 135091b4e487SEugen Hristev 135191b4e487SEugen Hristev /* 135291b4e487SEugen Hristev * the offset is then taken and converted to 2's complements, 135391b4e487SEugen Hristev * and must be negative, as we subtract this value from the 135491b4e487SEugen Hristev * color components 135591b4e487SEugen Hristev */ 135691b4e487SEugen Hristev ctrls->offset[c] = -ctrls->offset[c]; 135791b4e487SEugen Hristev 135891b4e487SEugen Hristev /* 135991b4e487SEugen Hristev * the stretch gain is the total number of histogram bins 136091b4e487SEugen Hristev * divided by the actual range of color component (Max - Min) 136191b4e487SEugen Hristev * If we compute gain like this, the actual color component 136291b4e487SEugen Hristev * will be stretched to the full histogram. 136391b4e487SEugen Hristev * We need to shift 9 bits for precision, we have 9 bits for 136491b4e487SEugen Hristev * decimals 136591b4e487SEugen Hristev */ 136691b4e487SEugen Hristev s_gain[c] = (HIST_ENTRIES << 9) / 136791b4e487SEugen Hristev (ctrls->hist_minmax[c][HIST_MAX_INDEX] - 136891b4e487SEugen Hristev ctrls->hist_minmax[c][HIST_MIN_INDEX] + 1); 136991b4e487SEugen Hristev 137091b4e487SEugen Hristev /* 137191b4e487SEugen Hristev * Now we have to compute the gain w.r.t. the average. 137291b4e487SEugen Hristev * Add/lose gain to the component towards the average. 137391b4e487SEugen Hristev * If it happens that the component is zero, use the 137491b4e487SEugen Hristev * fixed point value : 1.0 gain. 137591b4e487SEugen Hristev */ 137691b4e487SEugen Hristev if (hist_count[c]) 137791b4e487SEugen Hristev gw_gain[c] = div_u64(avg << 9, hist_count[c]); 137891b4e487SEugen Hristev else 137991b4e487SEugen Hristev gw_gain[c] = 1 << 9; 138091b4e487SEugen Hristev 138191b4e487SEugen Hristev v4l2_dbg(1, debug, &isc->v4l2_dev, 138291b4e487SEugen Hristev "isc wb: component %d, s_gain %u, gw_gain %u\n", 138391b4e487SEugen Hristev c, s_gain[c], gw_gain[c]); 138491b4e487SEugen Hristev /* multiply both gains and adjust for decimals */ 138591b4e487SEugen Hristev ctrls->gain[c] = s_gain[c] * gw_gain[c]; 138691b4e487SEugen Hristev ctrls->gain[c] >>= 9; 138791b4e487SEugen Hristev 138891b4e487SEugen Hristev /* make sure we are not out of range */ 138991b4e487SEugen Hristev ctrls->gain[c] = clamp_val(ctrls->gain[c], 0, GENMASK(12, 0)); 139091b4e487SEugen Hristev 139191b4e487SEugen Hristev v4l2_dbg(1, debug, &isc->v4l2_dev, 139291b4e487SEugen Hristev "isc wb: component %d, final gain %u\n", 139391b4e487SEugen Hristev c, ctrls->gain[c]); 139491b4e487SEugen Hristev } 139591b4e487SEugen Hristev } 139691b4e487SEugen Hristev 139791b4e487SEugen Hristev static void isc_awb_work(struct work_struct *w) 139891b4e487SEugen Hristev { 139991b4e487SEugen Hristev struct isc_device *isc = 140091b4e487SEugen Hristev container_of(w, struct isc_device, awb_work); 140191b4e487SEugen Hristev struct regmap *regmap = isc->regmap; 140291b4e487SEugen Hristev struct isc_ctrls *ctrls = &isc->ctrls; 140391b4e487SEugen Hristev u32 hist_id = ctrls->hist_id; 140491b4e487SEugen Hristev u32 baysel; 140591b4e487SEugen Hristev unsigned long flags; 140691b4e487SEugen Hristev u32 min, max; 140791b4e487SEugen Hristev int ret; 140891b4e487SEugen Hristev 140991b4e487SEugen Hristev if (ctrls->hist_stat != HIST_ENABLED) 141091b4e487SEugen Hristev return; 141191b4e487SEugen Hristev 141291b4e487SEugen Hristev isc_hist_count(isc, &min, &max); 141391b4e487SEugen Hristev 141491b4e487SEugen Hristev v4l2_dbg(1, debug, &isc->v4l2_dev, 141591b4e487SEugen Hristev "isc wb mode %d: hist min %u , max %u\n", hist_id, min, max); 141691b4e487SEugen Hristev 141791b4e487SEugen Hristev ctrls->hist_minmax[hist_id][HIST_MIN_INDEX] = min; 141891b4e487SEugen Hristev ctrls->hist_minmax[hist_id][HIST_MAX_INDEX] = max; 141991b4e487SEugen Hristev 142091b4e487SEugen Hristev if (hist_id != ISC_HIS_CFG_MODE_B) { 142191b4e487SEugen Hristev hist_id++; 142291b4e487SEugen Hristev } else { 142391b4e487SEugen Hristev isc_wb_update(ctrls); 142491b4e487SEugen Hristev hist_id = ISC_HIS_CFG_MODE_GR; 142591b4e487SEugen Hristev } 142691b4e487SEugen Hristev 142791b4e487SEugen Hristev ctrls->hist_id = hist_id; 142891b4e487SEugen Hristev baysel = isc->config.sd_format->cfa_baycfg << ISC_HIS_CFG_BAYSEL_SHIFT; 142991b4e487SEugen Hristev 143091b4e487SEugen Hristev ret = pm_runtime_resume_and_get(isc->dev); 143191b4e487SEugen Hristev if (ret < 0) 143291b4e487SEugen Hristev return; 143391b4e487SEugen Hristev 143491b4e487SEugen Hristev /* 143591b4e487SEugen Hristev * only update if we have all the required histograms and controls 143691b4e487SEugen Hristev * if awb has been disabled, we need to reset registers as well. 143791b4e487SEugen Hristev */ 143891b4e487SEugen Hristev if (hist_id == ISC_HIS_CFG_MODE_GR || ctrls->awb == ISC_WB_NONE) { 143991b4e487SEugen Hristev /* 144091b4e487SEugen Hristev * It may happen that DMA Done IRQ will trigger while we are 144191b4e487SEugen Hristev * updating white balance registers here. 144291b4e487SEugen Hristev * In that case, only parts of the controls have been updated. 144391b4e487SEugen Hristev * We can avoid that by locking the section. 144491b4e487SEugen Hristev */ 144591b4e487SEugen Hristev spin_lock_irqsave(&isc->awb_lock, flags); 144691b4e487SEugen Hristev isc_update_awb_ctrls(isc); 144791b4e487SEugen Hristev spin_unlock_irqrestore(&isc->awb_lock, flags); 144891b4e487SEugen Hristev 144991b4e487SEugen Hristev /* 145091b4e487SEugen Hristev * if we are doing just the one time white balance adjustment, 145191b4e487SEugen Hristev * we are basically done. 145291b4e487SEugen Hristev */ 145391b4e487SEugen Hristev if (ctrls->awb == ISC_WB_ONETIME) { 145491b4e487SEugen Hristev v4l2_info(&isc->v4l2_dev, 145591b4e487SEugen Hristev "Completed one time white-balance adjustment.\n"); 145691b4e487SEugen Hristev /* update the v4l2 controls values */ 145791b4e487SEugen Hristev isc_update_v4l2_ctrls(isc); 145891b4e487SEugen Hristev ctrls->awb = ISC_WB_NONE; 145991b4e487SEugen Hristev } 146091b4e487SEugen Hristev } 146191b4e487SEugen Hristev regmap_write(regmap, ISC_HIS_CFG + isc->offsets.his, 146291b4e487SEugen Hristev hist_id | baysel | ISC_HIS_CFG_RAR); 146391b4e487SEugen Hristev 146491b4e487SEugen Hristev /* 146591b4e487SEugen Hristev * We have to make sure the streaming has not stopped meanwhile. 146691b4e487SEugen Hristev * ISC requires a frame to clock the internal profile update. 146791b4e487SEugen Hristev * To avoid issues, lock the sequence with a mutex 146891b4e487SEugen Hristev */ 146991b4e487SEugen Hristev mutex_lock(&isc->awb_mutex); 147091b4e487SEugen Hristev 147191b4e487SEugen Hristev /* streaming is not active anymore */ 147291b4e487SEugen Hristev if (isc->stop) { 147391b4e487SEugen Hristev mutex_unlock(&isc->awb_mutex); 147491b4e487SEugen Hristev return; 147591b4e487SEugen Hristev } 147691b4e487SEugen Hristev 147791b4e487SEugen Hristev isc_update_profile(isc); 147891b4e487SEugen Hristev 147991b4e487SEugen Hristev mutex_unlock(&isc->awb_mutex); 148091b4e487SEugen Hristev 148191b4e487SEugen Hristev /* if awb has been disabled, we don't need to start another histogram */ 148291b4e487SEugen Hristev if (ctrls->awb) 148391b4e487SEugen Hristev regmap_write(regmap, ISC_CTRLEN, ISC_CTRL_HISREQ); 148491b4e487SEugen Hristev 148591b4e487SEugen Hristev pm_runtime_put_sync(isc->dev); 148691b4e487SEugen Hristev } 148791b4e487SEugen Hristev 148891b4e487SEugen Hristev static int isc_s_ctrl(struct v4l2_ctrl *ctrl) 148991b4e487SEugen Hristev { 149091b4e487SEugen Hristev struct isc_device *isc = container_of(ctrl->handler, 149191b4e487SEugen Hristev struct isc_device, ctrls.handler); 149291b4e487SEugen Hristev struct isc_ctrls *ctrls = &isc->ctrls; 149391b4e487SEugen Hristev 149491b4e487SEugen Hristev if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE) 149591b4e487SEugen Hristev return 0; 149691b4e487SEugen Hristev 149791b4e487SEugen Hristev switch (ctrl->id) { 149891b4e487SEugen Hristev case V4L2_CID_BRIGHTNESS: 149991b4e487SEugen Hristev ctrls->brightness = ctrl->val & ISC_CBC_BRIGHT_MASK; 150091b4e487SEugen Hristev break; 150191b4e487SEugen Hristev case V4L2_CID_CONTRAST: 150291b4e487SEugen Hristev ctrls->contrast = ctrl->val & ISC_CBC_CONTRAST_MASK; 150391b4e487SEugen Hristev break; 150491b4e487SEugen Hristev case V4L2_CID_GAMMA: 150591b4e487SEugen Hristev ctrls->gamma_index = ctrl->val; 150691b4e487SEugen Hristev break; 150791b4e487SEugen Hristev default: 150891b4e487SEugen Hristev return -EINVAL; 150991b4e487SEugen Hristev } 151091b4e487SEugen Hristev 151191b4e487SEugen Hristev return 0; 151291b4e487SEugen Hristev } 151391b4e487SEugen Hristev 151491b4e487SEugen Hristev static const struct v4l2_ctrl_ops isc_ctrl_ops = { 151591b4e487SEugen Hristev .s_ctrl = isc_s_ctrl, 151691b4e487SEugen Hristev }; 151791b4e487SEugen Hristev 151891b4e487SEugen Hristev static int isc_s_awb_ctrl(struct v4l2_ctrl *ctrl) 151991b4e487SEugen Hristev { 152091b4e487SEugen Hristev struct isc_device *isc = container_of(ctrl->handler, 152191b4e487SEugen Hristev struct isc_device, ctrls.handler); 152291b4e487SEugen Hristev struct isc_ctrls *ctrls = &isc->ctrls; 152391b4e487SEugen Hristev 152491b4e487SEugen Hristev if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE) 152591b4e487SEugen Hristev return 0; 152691b4e487SEugen Hristev 152791b4e487SEugen Hristev switch (ctrl->id) { 152891b4e487SEugen Hristev case V4L2_CID_AUTO_WHITE_BALANCE: 152991b4e487SEugen Hristev if (ctrl->val == 1) 153091b4e487SEugen Hristev ctrls->awb = ISC_WB_AUTO; 153191b4e487SEugen Hristev else 153291b4e487SEugen Hristev ctrls->awb = ISC_WB_NONE; 153391b4e487SEugen Hristev 153491b4e487SEugen Hristev /* configure the controls with new values from v4l2 */ 153591b4e487SEugen Hristev if (ctrl->cluster[ISC_CTRL_R_GAIN]->is_new) 153691b4e487SEugen Hristev ctrls->gain[ISC_HIS_CFG_MODE_R] = isc->r_gain_ctrl->val; 153791b4e487SEugen Hristev if (ctrl->cluster[ISC_CTRL_B_GAIN]->is_new) 153891b4e487SEugen Hristev ctrls->gain[ISC_HIS_CFG_MODE_B] = isc->b_gain_ctrl->val; 153991b4e487SEugen Hristev if (ctrl->cluster[ISC_CTRL_GR_GAIN]->is_new) 154091b4e487SEugen Hristev ctrls->gain[ISC_HIS_CFG_MODE_GR] = isc->gr_gain_ctrl->val; 154191b4e487SEugen Hristev if (ctrl->cluster[ISC_CTRL_GB_GAIN]->is_new) 154291b4e487SEugen Hristev ctrls->gain[ISC_HIS_CFG_MODE_GB] = isc->gb_gain_ctrl->val; 154391b4e487SEugen Hristev 154491b4e487SEugen Hristev if (ctrl->cluster[ISC_CTRL_R_OFF]->is_new) 154591b4e487SEugen Hristev ctrls->offset[ISC_HIS_CFG_MODE_R] = isc->r_off_ctrl->val; 154691b4e487SEugen Hristev if (ctrl->cluster[ISC_CTRL_B_OFF]->is_new) 154791b4e487SEugen Hristev ctrls->offset[ISC_HIS_CFG_MODE_B] = isc->b_off_ctrl->val; 154891b4e487SEugen Hristev if (ctrl->cluster[ISC_CTRL_GR_OFF]->is_new) 154991b4e487SEugen Hristev ctrls->offset[ISC_HIS_CFG_MODE_GR] = isc->gr_off_ctrl->val; 155091b4e487SEugen Hristev if (ctrl->cluster[ISC_CTRL_GB_OFF]->is_new) 155191b4e487SEugen Hristev ctrls->offset[ISC_HIS_CFG_MODE_GB] = isc->gb_off_ctrl->val; 155291b4e487SEugen Hristev 155391b4e487SEugen Hristev isc_update_awb_ctrls(isc); 155491b4e487SEugen Hristev 155591b4e487SEugen Hristev mutex_lock(&isc->awb_mutex); 155691b4e487SEugen Hristev if (vb2_is_streaming(&isc->vb2_vidq)) { 155791b4e487SEugen Hristev /* 155891b4e487SEugen Hristev * If we are streaming, we can update profile to 155991b4e487SEugen Hristev * have the new settings in place. 156091b4e487SEugen Hristev */ 156191b4e487SEugen Hristev isc_update_profile(isc); 156291b4e487SEugen Hristev } else { 156391b4e487SEugen Hristev /* 156491b4e487SEugen Hristev * The auto cluster will activate automatically this 156591b4e487SEugen Hristev * control. This has to be deactivated when not 156691b4e487SEugen Hristev * streaming. 156791b4e487SEugen Hristev */ 156891b4e487SEugen Hristev v4l2_ctrl_activate(isc->do_wb_ctrl, false); 156991b4e487SEugen Hristev } 157091b4e487SEugen Hristev mutex_unlock(&isc->awb_mutex); 157191b4e487SEugen Hristev 157291b4e487SEugen Hristev /* if we have autowhitebalance on, start histogram procedure */ 157391b4e487SEugen Hristev if (ctrls->awb == ISC_WB_AUTO && 157491b4e487SEugen Hristev vb2_is_streaming(&isc->vb2_vidq) && 157591b4e487SEugen Hristev ISC_IS_FORMAT_RAW(isc->config.sd_format->mbus_code)) 157691b4e487SEugen Hristev isc_set_histogram(isc, true); 157791b4e487SEugen Hristev 157891b4e487SEugen Hristev /* 157991b4e487SEugen Hristev * for one time whitebalance adjustment, check the button, 158091b4e487SEugen Hristev * if it's pressed, perform the one time operation. 158191b4e487SEugen Hristev */ 158291b4e487SEugen Hristev if (ctrls->awb == ISC_WB_NONE && 158391b4e487SEugen Hristev ctrl->cluster[ISC_CTRL_DO_WB]->is_new && 158491b4e487SEugen Hristev !(ctrl->cluster[ISC_CTRL_DO_WB]->flags & 158591b4e487SEugen Hristev V4L2_CTRL_FLAG_INACTIVE)) { 158691b4e487SEugen Hristev ctrls->awb = ISC_WB_ONETIME; 158791b4e487SEugen Hristev isc_set_histogram(isc, true); 158891b4e487SEugen Hristev v4l2_dbg(1, debug, &isc->v4l2_dev, 158991b4e487SEugen Hristev "One time white-balance started.\n"); 159091b4e487SEugen Hristev } 159191b4e487SEugen Hristev return 0; 159291b4e487SEugen Hristev } 159391b4e487SEugen Hristev return 0; 159491b4e487SEugen Hristev } 159591b4e487SEugen Hristev 159691b4e487SEugen Hristev static int isc_g_volatile_awb_ctrl(struct v4l2_ctrl *ctrl) 159791b4e487SEugen Hristev { 159891b4e487SEugen Hristev struct isc_device *isc = container_of(ctrl->handler, 159991b4e487SEugen Hristev struct isc_device, ctrls.handler); 160091b4e487SEugen Hristev struct isc_ctrls *ctrls = &isc->ctrls; 160191b4e487SEugen Hristev 160291b4e487SEugen Hristev switch (ctrl->id) { 160391b4e487SEugen Hristev /* being a cluster, this id will be called for every control */ 160491b4e487SEugen Hristev case V4L2_CID_AUTO_WHITE_BALANCE: 160591b4e487SEugen Hristev ctrl->cluster[ISC_CTRL_R_GAIN]->val = 160691b4e487SEugen Hristev ctrls->gain[ISC_HIS_CFG_MODE_R]; 160791b4e487SEugen Hristev ctrl->cluster[ISC_CTRL_B_GAIN]->val = 160891b4e487SEugen Hristev ctrls->gain[ISC_HIS_CFG_MODE_B]; 160991b4e487SEugen Hristev ctrl->cluster[ISC_CTRL_GR_GAIN]->val = 161091b4e487SEugen Hristev ctrls->gain[ISC_HIS_CFG_MODE_GR]; 161191b4e487SEugen Hristev ctrl->cluster[ISC_CTRL_GB_GAIN]->val = 161291b4e487SEugen Hristev ctrls->gain[ISC_HIS_CFG_MODE_GB]; 161391b4e487SEugen Hristev 161491b4e487SEugen Hristev ctrl->cluster[ISC_CTRL_R_OFF]->val = 161591b4e487SEugen Hristev ctrls->offset[ISC_HIS_CFG_MODE_R]; 161691b4e487SEugen Hristev ctrl->cluster[ISC_CTRL_B_OFF]->val = 161791b4e487SEugen Hristev ctrls->offset[ISC_HIS_CFG_MODE_B]; 161891b4e487SEugen Hristev ctrl->cluster[ISC_CTRL_GR_OFF]->val = 161991b4e487SEugen Hristev ctrls->offset[ISC_HIS_CFG_MODE_GR]; 162091b4e487SEugen Hristev ctrl->cluster[ISC_CTRL_GB_OFF]->val = 162191b4e487SEugen Hristev ctrls->offset[ISC_HIS_CFG_MODE_GB]; 162291b4e487SEugen Hristev break; 162391b4e487SEugen Hristev } 162491b4e487SEugen Hristev return 0; 162591b4e487SEugen Hristev } 162691b4e487SEugen Hristev 162791b4e487SEugen Hristev static const struct v4l2_ctrl_ops isc_awb_ops = { 162891b4e487SEugen Hristev .s_ctrl = isc_s_awb_ctrl, 162991b4e487SEugen Hristev .g_volatile_ctrl = isc_g_volatile_awb_ctrl, 163091b4e487SEugen Hristev }; 163191b4e487SEugen Hristev 163291b4e487SEugen Hristev #define ISC_CTRL_OFF(_name, _id, _name_str) \ 163391b4e487SEugen Hristev static const struct v4l2_ctrl_config _name = { \ 163491b4e487SEugen Hristev .ops = &isc_awb_ops, \ 163591b4e487SEugen Hristev .id = _id, \ 163691b4e487SEugen Hristev .name = _name_str, \ 163791b4e487SEugen Hristev .type = V4L2_CTRL_TYPE_INTEGER, \ 163891b4e487SEugen Hristev .flags = V4L2_CTRL_FLAG_SLIDER, \ 163991b4e487SEugen Hristev .min = -4095, \ 164091b4e487SEugen Hristev .max = 4095, \ 164191b4e487SEugen Hristev .step = 1, \ 164291b4e487SEugen Hristev .def = 0, \ 164391b4e487SEugen Hristev } 164491b4e487SEugen Hristev 164591b4e487SEugen Hristev ISC_CTRL_OFF(isc_r_off_ctrl, ISC_CID_R_OFFSET, "Red Component Offset"); 164691b4e487SEugen Hristev ISC_CTRL_OFF(isc_b_off_ctrl, ISC_CID_B_OFFSET, "Blue Component Offset"); 164791b4e487SEugen Hristev ISC_CTRL_OFF(isc_gr_off_ctrl, ISC_CID_GR_OFFSET, "Green Red Component Offset"); 164891b4e487SEugen Hristev ISC_CTRL_OFF(isc_gb_off_ctrl, ISC_CID_GB_OFFSET, "Green Blue Component Offset"); 164991b4e487SEugen Hristev 165091b4e487SEugen Hristev #define ISC_CTRL_GAIN(_name, _id, _name_str) \ 165191b4e487SEugen Hristev static const struct v4l2_ctrl_config _name = { \ 165291b4e487SEugen Hristev .ops = &isc_awb_ops, \ 165391b4e487SEugen Hristev .id = _id, \ 165491b4e487SEugen Hristev .name = _name_str, \ 165591b4e487SEugen Hristev .type = V4L2_CTRL_TYPE_INTEGER, \ 165691b4e487SEugen Hristev .flags = V4L2_CTRL_FLAG_SLIDER, \ 165791b4e487SEugen Hristev .min = 0, \ 165891b4e487SEugen Hristev .max = 8191, \ 165991b4e487SEugen Hristev .step = 1, \ 166091b4e487SEugen Hristev .def = 512, \ 166191b4e487SEugen Hristev } 166291b4e487SEugen Hristev 166391b4e487SEugen Hristev ISC_CTRL_GAIN(isc_r_gain_ctrl, ISC_CID_R_GAIN, "Red Component Gain"); 166491b4e487SEugen Hristev ISC_CTRL_GAIN(isc_b_gain_ctrl, ISC_CID_B_GAIN, "Blue Component Gain"); 166591b4e487SEugen Hristev ISC_CTRL_GAIN(isc_gr_gain_ctrl, ISC_CID_GR_GAIN, "Green Red Component Gain"); 166691b4e487SEugen Hristev ISC_CTRL_GAIN(isc_gb_gain_ctrl, ISC_CID_GB_GAIN, "Green Blue Component Gain"); 166791b4e487SEugen Hristev 166891b4e487SEugen Hristev static int isc_ctrl_init(struct isc_device *isc) 166991b4e487SEugen Hristev { 167091b4e487SEugen Hristev const struct v4l2_ctrl_ops *ops = &isc_ctrl_ops; 167191b4e487SEugen Hristev struct isc_ctrls *ctrls = &isc->ctrls; 167291b4e487SEugen Hristev struct v4l2_ctrl_handler *hdl = &ctrls->handler; 167391b4e487SEugen Hristev int ret; 167491b4e487SEugen Hristev 167591b4e487SEugen Hristev ctrls->hist_stat = HIST_INIT; 167691b4e487SEugen Hristev isc_reset_awb_ctrls(isc); 167791b4e487SEugen Hristev 167891b4e487SEugen Hristev ret = v4l2_ctrl_handler_init(hdl, 13); 167991b4e487SEugen Hristev if (ret < 0) 168091b4e487SEugen Hristev return ret; 168191b4e487SEugen Hristev 168291b4e487SEugen Hristev /* Initialize product specific controls. For example, contrast */ 168391b4e487SEugen Hristev isc->config_ctrls(isc, ops); 168491b4e487SEugen Hristev 168591b4e487SEugen Hristev ctrls->brightness = 0; 168691b4e487SEugen Hristev 168791b4e487SEugen Hristev v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BRIGHTNESS, -1024, 1023, 1, 0); 168891b4e487SEugen Hristev v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAMMA, 0, isc->gamma_max, 1, 168991b4e487SEugen Hristev isc->gamma_max); 169091b4e487SEugen Hristev isc->awb_ctrl = v4l2_ctrl_new_std(hdl, &isc_awb_ops, 169191b4e487SEugen Hristev V4L2_CID_AUTO_WHITE_BALANCE, 169291b4e487SEugen Hristev 0, 1, 1, 1); 169391b4e487SEugen Hristev 169491b4e487SEugen Hristev /* do_white_balance is a button, so min,max,step,default are ignored */ 169591b4e487SEugen Hristev isc->do_wb_ctrl = v4l2_ctrl_new_std(hdl, &isc_awb_ops, 169691b4e487SEugen Hristev V4L2_CID_DO_WHITE_BALANCE, 169791b4e487SEugen Hristev 0, 0, 0, 0); 169891b4e487SEugen Hristev 169991b4e487SEugen Hristev if (!isc->do_wb_ctrl) { 170091b4e487SEugen Hristev ret = hdl->error; 170191b4e487SEugen Hristev v4l2_ctrl_handler_free(hdl); 170291b4e487SEugen Hristev return ret; 170391b4e487SEugen Hristev } 170491b4e487SEugen Hristev 170591b4e487SEugen Hristev v4l2_ctrl_activate(isc->do_wb_ctrl, false); 170691b4e487SEugen Hristev 170791b4e487SEugen Hristev isc->r_gain_ctrl = v4l2_ctrl_new_custom(hdl, &isc_r_gain_ctrl, NULL); 170891b4e487SEugen Hristev isc->b_gain_ctrl = v4l2_ctrl_new_custom(hdl, &isc_b_gain_ctrl, NULL); 170991b4e487SEugen Hristev isc->gr_gain_ctrl = v4l2_ctrl_new_custom(hdl, &isc_gr_gain_ctrl, NULL); 171091b4e487SEugen Hristev isc->gb_gain_ctrl = v4l2_ctrl_new_custom(hdl, &isc_gb_gain_ctrl, NULL); 171191b4e487SEugen Hristev isc->r_off_ctrl = v4l2_ctrl_new_custom(hdl, &isc_r_off_ctrl, NULL); 171291b4e487SEugen Hristev isc->b_off_ctrl = v4l2_ctrl_new_custom(hdl, &isc_b_off_ctrl, NULL); 171391b4e487SEugen Hristev isc->gr_off_ctrl = v4l2_ctrl_new_custom(hdl, &isc_gr_off_ctrl, NULL); 171491b4e487SEugen Hristev isc->gb_off_ctrl = v4l2_ctrl_new_custom(hdl, &isc_gb_off_ctrl, NULL); 171591b4e487SEugen Hristev 171691b4e487SEugen Hristev /* 171791b4e487SEugen Hristev * The cluster is in auto mode with autowhitebalance enabled 171891b4e487SEugen Hristev * and manual mode otherwise. 171991b4e487SEugen Hristev */ 172091b4e487SEugen Hristev v4l2_ctrl_auto_cluster(10, &isc->awb_ctrl, 0, true); 172191b4e487SEugen Hristev 172291b4e487SEugen Hristev v4l2_ctrl_handler_setup(hdl); 172391b4e487SEugen Hristev 172491b4e487SEugen Hristev return 0; 172591b4e487SEugen Hristev } 172691b4e487SEugen Hristev 172791b4e487SEugen Hristev static int isc_async_bound(struct v4l2_async_notifier *notifier, 172891b4e487SEugen Hristev struct v4l2_subdev *subdev, 172991b4e487SEugen Hristev struct v4l2_async_subdev *asd) 173091b4e487SEugen Hristev { 173191b4e487SEugen Hristev struct isc_device *isc = container_of(notifier->v4l2_dev, 173291b4e487SEugen Hristev struct isc_device, v4l2_dev); 173391b4e487SEugen Hristev struct isc_subdev_entity *subdev_entity = 173491b4e487SEugen Hristev container_of(notifier, struct isc_subdev_entity, notifier); 1735*920b2665SEugen Hristev int pad; 173691b4e487SEugen Hristev 173791b4e487SEugen Hristev if (video_is_registered(&isc->video_dev)) { 173891b4e487SEugen Hristev v4l2_err(&isc->v4l2_dev, "only supports one sub-device.\n"); 173991b4e487SEugen Hristev return -EBUSY; 174091b4e487SEugen Hristev } 174191b4e487SEugen Hristev 174291b4e487SEugen Hristev subdev_entity->sd = subdev; 174391b4e487SEugen Hristev 1744*920b2665SEugen Hristev pad = media_entity_get_fwnode_pad(&subdev->entity, asd->match.fwnode, 1745*920b2665SEugen Hristev MEDIA_PAD_FL_SOURCE); 1746*920b2665SEugen Hristev if (pad < 0) { 1747*920b2665SEugen Hristev v4l2_err(&isc->v4l2_dev, "failed to find pad for %s\n", 1748*920b2665SEugen Hristev subdev->name); 1749*920b2665SEugen Hristev return pad; 1750*920b2665SEugen Hristev } 1751*920b2665SEugen Hristev 1752*920b2665SEugen Hristev isc->remote_pad = pad; 1753*920b2665SEugen Hristev 175491b4e487SEugen Hristev return 0; 175591b4e487SEugen Hristev } 175691b4e487SEugen Hristev 175791b4e487SEugen Hristev static void isc_async_unbind(struct v4l2_async_notifier *notifier, 175891b4e487SEugen Hristev struct v4l2_subdev *subdev, 175991b4e487SEugen Hristev struct v4l2_async_subdev *asd) 176091b4e487SEugen Hristev { 176191b4e487SEugen Hristev struct isc_device *isc = container_of(notifier->v4l2_dev, 176291b4e487SEugen Hristev struct isc_device, v4l2_dev); 176391b4e487SEugen Hristev mutex_destroy(&isc->awb_mutex); 176491b4e487SEugen Hristev cancel_work_sync(&isc->awb_work); 176591b4e487SEugen Hristev video_unregister_device(&isc->video_dev); 176691b4e487SEugen Hristev v4l2_ctrl_handler_free(&isc->ctrls.handler); 176791b4e487SEugen Hristev } 176891b4e487SEugen Hristev 1769*920b2665SEugen Hristev struct isc_format *isc_find_format_by_code(struct isc_device *isc, 177091b4e487SEugen Hristev unsigned int code, int *index) 177191b4e487SEugen Hristev { 177291b4e487SEugen Hristev struct isc_format *fmt = &isc->formats_list[0]; 177391b4e487SEugen Hristev unsigned int i; 177491b4e487SEugen Hristev 177591b4e487SEugen Hristev for (i = 0; i < isc->formats_list_size; i++) { 177691b4e487SEugen Hristev if (fmt->mbus_code == code) { 177791b4e487SEugen Hristev *index = i; 177891b4e487SEugen Hristev return fmt; 177991b4e487SEugen Hristev } 178091b4e487SEugen Hristev 178191b4e487SEugen Hristev fmt++; 178291b4e487SEugen Hristev } 178391b4e487SEugen Hristev 178491b4e487SEugen Hristev return NULL; 178591b4e487SEugen Hristev } 1786*920b2665SEugen Hristev EXPORT_SYMBOL_GPL(isc_find_format_by_code); 178791b4e487SEugen Hristev 178891b4e487SEugen Hristev static int isc_formats_init(struct isc_device *isc) 178991b4e487SEugen Hristev { 179091b4e487SEugen Hristev struct isc_format *fmt; 179191b4e487SEugen Hristev struct v4l2_subdev *subdev = isc->current_subdev->sd; 179291b4e487SEugen Hristev unsigned int num_fmts, i, j; 179391b4e487SEugen Hristev u32 list_size = isc->formats_list_size; 179491b4e487SEugen Hristev struct v4l2_subdev_mbus_code_enum mbus_code = { 179591b4e487SEugen Hristev .which = V4L2_SUBDEV_FORMAT_ACTIVE, 179691b4e487SEugen Hristev }; 179791b4e487SEugen Hristev 179891b4e487SEugen Hristev num_fmts = 0; 179991b4e487SEugen Hristev while (!v4l2_subdev_call(subdev, pad, enum_mbus_code, 180091b4e487SEugen Hristev NULL, &mbus_code)) { 180191b4e487SEugen Hristev mbus_code.index++; 180291b4e487SEugen Hristev 1803*920b2665SEugen Hristev fmt = isc_find_format_by_code(isc, mbus_code.code, &i); 180491b4e487SEugen Hristev if (!fmt) { 180591b4e487SEugen Hristev v4l2_warn(&isc->v4l2_dev, "Mbus code %x not supported\n", 180691b4e487SEugen Hristev mbus_code.code); 180791b4e487SEugen Hristev continue; 180891b4e487SEugen Hristev } 180991b4e487SEugen Hristev 181091b4e487SEugen Hristev fmt->sd_support = true; 181191b4e487SEugen Hristev num_fmts++; 181291b4e487SEugen Hristev } 181391b4e487SEugen Hristev 181491b4e487SEugen Hristev if (!num_fmts) 181591b4e487SEugen Hristev return -ENXIO; 181691b4e487SEugen Hristev 181791b4e487SEugen Hristev isc->num_user_formats = num_fmts; 181891b4e487SEugen Hristev isc->user_formats = devm_kcalloc(isc->dev, 181991b4e487SEugen Hristev num_fmts, sizeof(*isc->user_formats), 182091b4e487SEugen Hristev GFP_KERNEL); 182191b4e487SEugen Hristev if (!isc->user_formats) 182291b4e487SEugen Hristev return -ENOMEM; 182391b4e487SEugen Hristev 182491b4e487SEugen Hristev fmt = &isc->formats_list[0]; 182591b4e487SEugen Hristev for (i = 0, j = 0; i < list_size; i++) { 182691b4e487SEugen Hristev if (fmt->sd_support) 182791b4e487SEugen Hristev isc->user_formats[j++] = fmt; 182891b4e487SEugen Hristev fmt++; 182991b4e487SEugen Hristev } 183091b4e487SEugen Hristev 183191b4e487SEugen Hristev return 0; 183291b4e487SEugen Hristev } 183391b4e487SEugen Hristev 183491b4e487SEugen Hristev static int isc_set_default_fmt(struct isc_device *isc) 183591b4e487SEugen Hristev { 183691b4e487SEugen Hristev struct v4l2_format f = { 183791b4e487SEugen Hristev .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, 183891b4e487SEugen Hristev .fmt.pix = { 183991b4e487SEugen Hristev .width = VGA_WIDTH, 184091b4e487SEugen Hristev .height = VGA_HEIGHT, 184191b4e487SEugen Hristev .field = V4L2_FIELD_NONE, 184291b4e487SEugen Hristev .pixelformat = isc->user_formats[0]->fourcc, 184391b4e487SEugen Hristev }, 184491b4e487SEugen Hristev }; 184591b4e487SEugen Hristev int ret; 184691b4e487SEugen Hristev 184791b4e487SEugen Hristev ret = isc_try_fmt(isc, &f, NULL); 184891b4e487SEugen Hristev if (ret) 184991b4e487SEugen Hristev return ret; 185091b4e487SEugen Hristev 185191b4e487SEugen Hristev isc->fmt = f; 185291b4e487SEugen Hristev return 0; 185391b4e487SEugen Hristev } 185491b4e487SEugen Hristev 185591b4e487SEugen Hristev static int isc_async_complete(struct v4l2_async_notifier *notifier) 185691b4e487SEugen Hristev { 185791b4e487SEugen Hristev struct isc_device *isc = container_of(notifier->v4l2_dev, 185891b4e487SEugen Hristev struct isc_device, v4l2_dev); 185991b4e487SEugen Hristev struct video_device *vdev = &isc->video_dev; 186091b4e487SEugen Hristev struct vb2_queue *q = &isc->vb2_vidq; 186191b4e487SEugen Hristev int ret = 0; 186291b4e487SEugen Hristev 186391b4e487SEugen Hristev INIT_WORK(&isc->awb_work, isc_awb_work); 186491b4e487SEugen Hristev 186591b4e487SEugen Hristev ret = v4l2_device_register_subdev_nodes(&isc->v4l2_dev); 186691b4e487SEugen Hristev if (ret < 0) { 186791b4e487SEugen Hristev v4l2_err(&isc->v4l2_dev, "Failed to register subdev nodes\n"); 186891b4e487SEugen Hristev return ret; 186991b4e487SEugen Hristev } 187091b4e487SEugen Hristev 187191b4e487SEugen Hristev isc->current_subdev = container_of(notifier, 187291b4e487SEugen Hristev struct isc_subdev_entity, notifier); 187391b4e487SEugen Hristev mutex_init(&isc->lock); 187491b4e487SEugen Hristev mutex_init(&isc->awb_mutex); 187591b4e487SEugen Hristev 187691b4e487SEugen Hristev init_completion(&isc->comp); 187791b4e487SEugen Hristev 187891b4e487SEugen Hristev /* Initialize videobuf2 queue */ 187991b4e487SEugen Hristev q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 188091b4e487SEugen Hristev q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ; 188191b4e487SEugen Hristev q->drv_priv = isc; 188291b4e487SEugen Hristev q->buf_struct_size = sizeof(struct isc_buffer); 188391b4e487SEugen Hristev q->ops = &isc_vb2_ops; 188491b4e487SEugen Hristev q->mem_ops = &vb2_dma_contig_memops; 188591b4e487SEugen Hristev q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; 188691b4e487SEugen Hristev q->lock = &isc->lock; 188791b4e487SEugen Hristev q->min_buffers_needed = 1; 188891b4e487SEugen Hristev q->dev = isc->dev; 188991b4e487SEugen Hristev 189091b4e487SEugen Hristev ret = vb2_queue_init(q); 189191b4e487SEugen Hristev if (ret < 0) { 189291b4e487SEugen Hristev v4l2_err(&isc->v4l2_dev, 189391b4e487SEugen Hristev "vb2_queue_init() failed: %d\n", ret); 189491b4e487SEugen Hristev goto isc_async_complete_err; 189591b4e487SEugen Hristev } 189691b4e487SEugen Hristev 189791b4e487SEugen Hristev /* Init video dma queues */ 189891b4e487SEugen Hristev INIT_LIST_HEAD(&isc->dma_queue); 189991b4e487SEugen Hristev spin_lock_init(&isc->dma_queue_lock); 190091b4e487SEugen Hristev spin_lock_init(&isc->awb_lock); 190191b4e487SEugen Hristev 190291b4e487SEugen Hristev ret = isc_formats_init(isc); 190391b4e487SEugen Hristev if (ret < 0) { 190491b4e487SEugen Hristev v4l2_err(&isc->v4l2_dev, 190591b4e487SEugen Hristev "Init format failed: %d\n", ret); 190691b4e487SEugen Hristev goto isc_async_complete_err; 190791b4e487SEugen Hristev } 190891b4e487SEugen Hristev 190991b4e487SEugen Hristev ret = isc_set_default_fmt(isc); 191091b4e487SEugen Hristev if (ret) { 191191b4e487SEugen Hristev v4l2_err(&isc->v4l2_dev, "Could not set default format\n"); 191291b4e487SEugen Hristev goto isc_async_complete_err; 191391b4e487SEugen Hristev } 191491b4e487SEugen Hristev 191591b4e487SEugen Hristev ret = isc_ctrl_init(isc); 191691b4e487SEugen Hristev if (ret) { 191791b4e487SEugen Hristev v4l2_err(&isc->v4l2_dev, "Init isc ctrols failed: %d\n", ret); 191891b4e487SEugen Hristev goto isc_async_complete_err; 191991b4e487SEugen Hristev } 192091b4e487SEugen Hristev 192191b4e487SEugen Hristev /* Register video device */ 192291b4e487SEugen Hristev strscpy(vdev->name, KBUILD_MODNAME, sizeof(vdev->name)); 192391b4e487SEugen Hristev vdev->release = video_device_release_empty; 192491b4e487SEugen Hristev vdev->fops = &isc_fops; 192591b4e487SEugen Hristev vdev->ioctl_ops = &isc_ioctl_ops; 192691b4e487SEugen Hristev vdev->v4l2_dev = &isc->v4l2_dev; 192791b4e487SEugen Hristev vdev->vfl_dir = VFL_DIR_RX; 192891b4e487SEugen Hristev vdev->queue = q; 192991b4e487SEugen Hristev vdev->lock = &isc->lock; 193091b4e487SEugen Hristev vdev->ctrl_handler = &isc->ctrls.handler; 193191b4e487SEugen Hristev vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE; 193291b4e487SEugen Hristev video_set_drvdata(vdev, isc); 193391b4e487SEugen Hristev 193491b4e487SEugen Hristev ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); 193591b4e487SEugen Hristev if (ret < 0) { 193691b4e487SEugen Hristev v4l2_err(&isc->v4l2_dev, 193791b4e487SEugen Hristev "video_register_device failed: %d\n", ret); 193891b4e487SEugen Hristev goto isc_async_complete_err; 193991b4e487SEugen Hristev } 194091b4e487SEugen Hristev 1941*920b2665SEugen Hristev ret = isc_scaler_link(isc); 1942*920b2665SEugen Hristev if (ret < 0) 1943*920b2665SEugen Hristev goto isc_async_complete_unregister_device; 1944*920b2665SEugen Hristev 1945*920b2665SEugen Hristev ret = media_device_register(&isc->mdev); 1946*920b2665SEugen Hristev if (ret < 0) 1947*920b2665SEugen Hristev goto isc_async_complete_unregister_device; 1948*920b2665SEugen Hristev 194991b4e487SEugen Hristev return 0; 195091b4e487SEugen Hristev 1951*920b2665SEugen Hristev isc_async_complete_unregister_device: 1952*920b2665SEugen Hristev video_unregister_device(vdev); 1953*920b2665SEugen Hristev 195491b4e487SEugen Hristev isc_async_complete_err: 195591b4e487SEugen Hristev mutex_destroy(&isc->awb_mutex); 195691b4e487SEugen Hristev mutex_destroy(&isc->lock); 195791b4e487SEugen Hristev return ret; 195891b4e487SEugen Hristev } 195991b4e487SEugen Hristev 196091b4e487SEugen Hristev const struct v4l2_async_notifier_operations microchip_isc_async_ops = { 196191b4e487SEugen Hristev .bound = isc_async_bound, 196291b4e487SEugen Hristev .unbind = isc_async_unbind, 196391b4e487SEugen Hristev .complete = isc_async_complete, 196491b4e487SEugen Hristev }; 196591b4e487SEugen Hristev EXPORT_SYMBOL_GPL(microchip_isc_async_ops); 196691b4e487SEugen Hristev 196791b4e487SEugen Hristev void microchip_isc_subdev_cleanup(struct isc_device *isc) 196891b4e487SEugen Hristev { 196991b4e487SEugen Hristev struct isc_subdev_entity *subdev_entity; 197091b4e487SEugen Hristev 197191b4e487SEugen Hristev list_for_each_entry(subdev_entity, &isc->subdev_entities, list) { 197291b4e487SEugen Hristev v4l2_async_nf_unregister(&subdev_entity->notifier); 197391b4e487SEugen Hristev v4l2_async_nf_cleanup(&subdev_entity->notifier); 197491b4e487SEugen Hristev } 197591b4e487SEugen Hristev 197691b4e487SEugen Hristev INIT_LIST_HEAD(&isc->subdev_entities); 197791b4e487SEugen Hristev } 197891b4e487SEugen Hristev EXPORT_SYMBOL_GPL(microchip_isc_subdev_cleanup); 197991b4e487SEugen Hristev 198091b4e487SEugen Hristev int microchip_isc_pipeline_init(struct isc_device *isc) 198191b4e487SEugen Hristev { 198291b4e487SEugen Hristev struct device *dev = isc->dev; 198391b4e487SEugen Hristev struct regmap *regmap = isc->regmap; 198491b4e487SEugen Hristev struct regmap_field *regs; 198591b4e487SEugen Hristev unsigned int i; 198691b4e487SEugen Hristev 198791b4e487SEugen Hristev /* 198891b4e487SEugen Hristev * DPCEN-->GDCEN-->BLCEN-->WB-->CFA-->CC--> 198991b4e487SEugen Hristev * GAM-->VHXS-->CSC-->CBC-->SUB422-->SUB420 199091b4e487SEugen Hristev */ 199191b4e487SEugen Hristev const struct reg_field regfields[ISC_PIPE_LINE_NODE_NUM] = { 199291b4e487SEugen Hristev REG_FIELD(ISC_DPC_CTRL, 0, 0), 199391b4e487SEugen Hristev REG_FIELD(ISC_DPC_CTRL, 1, 1), 199491b4e487SEugen Hristev REG_FIELD(ISC_DPC_CTRL, 2, 2), 199591b4e487SEugen Hristev REG_FIELD(ISC_WB_CTRL, 0, 0), 199691b4e487SEugen Hristev REG_FIELD(ISC_CFA_CTRL, 0, 0), 199791b4e487SEugen Hristev REG_FIELD(ISC_CC_CTRL, 0, 0), 199891b4e487SEugen Hristev REG_FIELD(ISC_GAM_CTRL, 0, 0), 199991b4e487SEugen Hristev REG_FIELD(ISC_GAM_CTRL, 1, 1), 200091b4e487SEugen Hristev REG_FIELD(ISC_GAM_CTRL, 2, 2), 200191b4e487SEugen Hristev REG_FIELD(ISC_GAM_CTRL, 3, 3), 200291b4e487SEugen Hristev REG_FIELD(ISC_VHXS_CTRL, 0, 0), 200391b4e487SEugen Hristev REG_FIELD(ISC_CSC_CTRL + isc->offsets.csc, 0, 0), 200491b4e487SEugen Hristev REG_FIELD(ISC_CBC_CTRL + isc->offsets.cbc, 0, 0), 200591b4e487SEugen Hristev REG_FIELD(ISC_SUB422_CTRL + isc->offsets.sub422, 0, 0), 200691b4e487SEugen Hristev REG_FIELD(ISC_SUB420_CTRL + isc->offsets.sub420, 0, 0), 200791b4e487SEugen Hristev }; 200891b4e487SEugen Hristev 200991b4e487SEugen Hristev for (i = 0; i < ISC_PIPE_LINE_NODE_NUM; i++) { 201091b4e487SEugen Hristev regs = devm_regmap_field_alloc(dev, regmap, regfields[i]); 201191b4e487SEugen Hristev if (IS_ERR(regs)) 201291b4e487SEugen Hristev return PTR_ERR(regs); 201391b4e487SEugen Hristev 201491b4e487SEugen Hristev isc->pipeline[i] = regs; 201591b4e487SEugen Hristev } 201691b4e487SEugen Hristev 201791b4e487SEugen Hristev return 0; 201891b4e487SEugen Hristev } 201991b4e487SEugen Hristev EXPORT_SYMBOL_GPL(microchip_isc_pipeline_init); 202091b4e487SEugen Hristev 2021*920b2665SEugen Hristev int isc_mc_init(struct isc_device *isc, u32 ver) 2022*920b2665SEugen Hristev { 2023*920b2665SEugen Hristev const struct of_device_id *match; 2024*920b2665SEugen Hristev int ret; 2025*920b2665SEugen Hristev 2026*920b2665SEugen Hristev isc->video_dev.entity.function = MEDIA_ENT_F_IO_V4L; 2027*920b2665SEugen Hristev isc->video_dev.entity.flags = MEDIA_ENT_FL_DEFAULT; 2028*920b2665SEugen Hristev isc->pads[ISC_PAD_SINK].flags = MEDIA_PAD_FL_SINK; 2029*920b2665SEugen Hristev 2030*920b2665SEugen Hristev ret = media_entity_pads_init(&isc->video_dev.entity, ISC_PADS_NUM, 2031*920b2665SEugen Hristev isc->pads); 2032*920b2665SEugen Hristev if (ret < 0) { 2033*920b2665SEugen Hristev dev_err(isc->dev, "media entity init failed\n"); 2034*920b2665SEugen Hristev return ret; 2035*920b2665SEugen Hristev } 2036*920b2665SEugen Hristev 2037*920b2665SEugen Hristev isc->mdev.dev = isc->dev; 2038*920b2665SEugen Hristev 2039*920b2665SEugen Hristev match = of_match_node(isc->dev->driver->of_match_table, 2040*920b2665SEugen Hristev isc->dev->of_node); 2041*920b2665SEugen Hristev 2042*920b2665SEugen Hristev strscpy(isc->mdev.driver_name, KBUILD_MODNAME, 2043*920b2665SEugen Hristev sizeof(isc->mdev.driver_name)); 2044*920b2665SEugen Hristev strscpy(isc->mdev.model, match->compatible, sizeof(isc->mdev.model)); 2045*920b2665SEugen Hristev snprintf(isc->mdev.bus_info, sizeof(isc->mdev.bus_info), "platform:%s", 2046*920b2665SEugen Hristev isc->v4l2_dev.name); 2047*920b2665SEugen Hristev isc->mdev.hw_revision = ver; 2048*920b2665SEugen Hristev 2049*920b2665SEugen Hristev media_device_init(&isc->mdev); 2050*920b2665SEugen Hristev 2051*920b2665SEugen Hristev isc->v4l2_dev.mdev = &isc->mdev; 2052*920b2665SEugen Hristev 2053*920b2665SEugen Hristev return isc_scaler_init(isc); 2054*920b2665SEugen Hristev } 2055*920b2665SEugen Hristev EXPORT_SYMBOL_GPL(isc_mc_init); 2056*920b2665SEugen Hristev 2057*920b2665SEugen Hristev void isc_mc_cleanup(struct isc_device *isc) 2058*920b2665SEugen Hristev { 2059*920b2665SEugen Hristev media_entity_cleanup(&isc->video_dev.entity); 2060*920b2665SEugen Hristev media_device_cleanup(&isc->mdev); 2061*920b2665SEugen Hristev } 2062*920b2665SEugen Hristev EXPORT_SYMBOL_GPL(isc_mc_cleanup); 2063*920b2665SEugen Hristev 206491b4e487SEugen Hristev /* regmap configuration */ 206591b4e487SEugen Hristev #define MICROCHIP_ISC_REG_MAX 0xd5c 206691b4e487SEugen Hristev const struct regmap_config microchip_isc_regmap_config = { 206791b4e487SEugen Hristev .reg_bits = 32, 206891b4e487SEugen Hristev .reg_stride = 4, 206991b4e487SEugen Hristev .val_bits = 32, 207091b4e487SEugen Hristev .max_register = MICROCHIP_ISC_REG_MAX, 207191b4e487SEugen Hristev }; 207291b4e487SEugen Hristev EXPORT_SYMBOL_GPL(microchip_isc_regmap_config); 207391b4e487SEugen Hristev 207491b4e487SEugen Hristev MODULE_AUTHOR("Songjun Wu"); 207591b4e487SEugen Hristev MODULE_AUTHOR("Eugen Hristev"); 207691b4e487SEugen Hristev MODULE_DESCRIPTION("Microchip ISC common code base"); 207791b4e487SEugen Hristev MODULE_LICENSE("GPL v2"); 2078