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 #define ISC_IS_FORMAT_RAW(mbus_code) \ 3691b4e487SEugen Hristev (((mbus_code) & 0xf000) == 0x3000) 3791b4e487SEugen Hristev 3891b4e487SEugen Hristev #define ISC_IS_FORMAT_GREY(mbus_code) \ 3991b4e487SEugen Hristev (((mbus_code) == MEDIA_BUS_FMT_Y10_1X10) | \ 4091b4e487SEugen Hristev (((mbus_code) == MEDIA_BUS_FMT_Y8_1X8))) 4191b4e487SEugen Hristev 4291b4e487SEugen Hristev static inline void isc_update_v4l2_ctrls(struct isc_device *isc) 4391b4e487SEugen Hristev { 4491b4e487SEugen Hristev struct isc_ctrls *ctrls = &isc->ctrls; 4591b4e487SEugen Hristev 4691b4e487SEugen Hristev /* In here we set the v4l2 controls w.r.t. our pipeline config */ 4791b4e487SEugen Hristev v4l2_ctrl_s_ctrl(isc->r_gain_ctrl, ctrls->gain[ISC_HIS_CFG_MODE_R]); 4891b4e487SEugen Hristev v4l2_ctrl_s_ctrl(isc->b_gain_ctrl, ctrls->gain[ISC_HIS_CFG_MODE_B]); 4991b4e487SEugen Hristev v4l2_ctrl_s_ctrl(isc->gr_gain_ctrl, ctrls->gain[ISC_HIS_CFG_MODE_GR]); 5091b4e487SEugen Hristev v4l2_ctrl_s_ctrl(isc->gb_gain_ctrl, ctrls->gain[ISC_HIS_CFG_MODE_GB]); 5191b4e487SEugen Hristev 5291b4e487SEugen Hristev v4l2_ctrl_s_ctrl(isc->r_off_ctrl, ctrls->offset[ISC_HIS_CFG_MODE_R]); 5391b4e487SEugen Hristev v4l2_ctrl_s_ctrl(isc->b_off_ctrl, ctrls->offset[ISC_HIS_CFG_MODE_B]); 5491b4e487SEugen Hristev v4l2_ctrl_s_ctrl(isc->gr_off_ctrl, ctrls->offset[ISC_HIS_CFG_MODE_GR]); 5591b4e487SEugen Hristev v4l2_ctrl_s_ctrl(isc->gb_off_ctrl, ctrls->offset[ISC_HIS_CFG_MODE_GB]); 5691b4e487SEugen Hristev } 5791b4e487SEugen Hristev 5891b4e487SEugen Hristev static inline void isc_update_awb_ctrls(struct isc_device *isc) 5991b4e487SEugen Hristev { 6091b4e487SEugen Hristev struct isc_ctrls *ctrls = &isc->ctrls; 6191b4e487SEugen Hristev 6291b4e487SEugen Hristev /* In here we set our actual hw pipeline config */ 6391b4e487SEugen Hristev 6491b4e487SEugen Hristev regmap_write(isc->regmap, ISC_WB_O_RGR, 6591b4e487SEugen Hristev ((ctrls->offset[ISC_HIS_CFG_MODE_R])) | 6691b4e487SEugen Hristev ((ctrls->offset[ISC_HIS_CFG_MODE_GR]) << 16)); 6791b4e487SEugen Hristev regmap_write(isc->regmap, ISC_WB_O_BGB, 6891b4e487SEugen Hristev ((ctrls->offset[ISC_HIS_CFG_MODE_B])) | 6991b4e487SEugen Hristev ((ctrls->offset[ISC_HIS_CFG_MODE_GB]) << 16)); 7091b4e487SEugen Hristev regmap_write(isc->regmap, ISC_WB_G_RGR, 7191b4e487SEugen Hristev ctrls->gain[ISC_HIS_CFG_MODE_R] | 7291b4e487SEugen Hristev (ctrls->gain[ISC_HIS_CFG_MODE_GR] << 16)); 7391b4e487SEugen Hristev regmap_write(isc->regmap, ISC_WB_G_BGB, 7491b4e487SEugen Hristev ctrls->gain[ISC_HIS_CFG_MODE_B] | 7591b4e487SEugen Hristev (ctrls->gain[ISC_HIS_CFG_MODE_GB] << 16)); 7691b4e487SEugen Hristev } 7791b4e487SEugen Hristev 7891b4e487SEugen Hristev static inline void isc_reset_awb_ctrls(struct isc_device *isc) 7991b4e487SEugen Hristev { 8091b4e487SEugen Hristev unsigned int c; 8191b4e487SEugen Hristev 8291b4e487SEugen Hristev for (c = ISC_HIS_CFG_MODE_GR; c <= ISC_HIS_CFG_MODE_B; c++) { 8391b4e487SEugen Hristev /* gains have a fixed point at 9 decimals */ 8491b4e487SEugen Hristev isc->ctrls.gain[c] = 1 << 9; 8591b4e487SEugen Hristev /* offsets are in 2's complements */ 8691b4e487SEugen Hristev isc->ctrls.offset[c] = 0; 8791b4e487SEugen Hristev } 8891b4e487SEugen Hristev } 8991b4e487SEugen Hristev 9091b4e487SEugen Hristev static int isc_queue_setup(struct vb2_queue *vq, 9191b4e487SEugen Hristev unsigned int *nbuffers, unsigned int *nplanes, 9291b4e487SEugen Hristev unsigned int sizes[], struct device *alloc_devs[]) 9391b4e487SEugen Hristev { 9491b4e487SEugen Hristev struct isc_device *isc = vb2_get_drv_priv(vq); 9591b4e487SEugen Hristev unsigned int size = isc->fmt.fmt.pix.sizeimage; 9691b4e487SEugen Hristev 9791b4e487SEugen Hristev if (*nplanes) 9891b4e487SEugen Hristev return sizes[0] < size ? -EINVAL : 0; 9991b4e487SEugen Hristev 10091b4e487SEugen Hristev *nplanes = 1; 10191b4e487SEugen Hristev sizes[0] = size; 10291b4e487SEugen Hristev 10391b4e487SEugen Hristev return 0; 10491b4e487SEugen Hristev } 10591b4e487SEugen Hristev 10691b4e487SEugen Hristev static int isc_buffer_prepare(struct vb2_buffer *vb) 10791b4e487SEugen Hristev { 10891b4e487SEugen Hristev struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 10991b4e487SEugen Hristev struct isc_device *isc = vb2_get_drv_priv(vb->vb2_queue); 11091b4e487SEugen Hristev unsigned long size = isc->fmt.fmt.pix.sizeimage; 11191b4e487SEugen Hristev 11291b4e487SEugen Hristev if (vb2_plane_size(vb, 0) < size) { 113*8d46c5cdSEugen Hristev dev_err(isc->dev, "buffer too small (%lu < %lu)\n", 11491b4e487SEugen Hristev vb2_plane_size(vb, 0), size); 11591b4e487SEugen Hristev return -EINVAL; 11691b4e487SEugen Hristev } 11791b4e487SEugen Hristev 11891b4e487SEugen Hristev vb2_set_plane_payload(vb, 0, size); 11991b4e487SEugen Hristev 12091b4e487SEugen Hristev vbuf->field = isc->fmt.fmt.pix.field; 12191b4e487SEugen Hristev 12291b4e487SEugen Hristev return 0; 12391b4e487SEugen Hristev } 12491b4e487SEugen Hristev 12591b4e487SEugen Hristev static void isc_crop_pfe(struct isc_device *isc) 12691b4e487SEugen Hristev { 12791b4e487SEugen Hristev struct regmap *regmap = isc->regmap; 12891b4e487SEugen Hristev u32 h, w; 12991b4e487SEugen Hristev 13091b4e487SEugen Hristev h = isc->fmt.fmt.pix.height; 13191b4e487SEugen Hristev w = isc->fmt.fmt.pix.width; 13291b4e487SEugen Hristev 13391b4e487SEugen Hristev /* 13491b4e487SEugen Hristev * In case the sensor is not RAW, it will output a pixel (12-16 bits) 13591b4e487SEugen Hristev * with two samples on the ISC Data bus (which is 8-12) 13691b4e487SEugen Hristev * ISC will count each sample, so, we need to multiply these values 13791b4e487SEugen Hristev * by two, to get the real number of samples for the required pixels. 13891b4e487SEugen Hristev */ 13991b4e487SEugen Hristev if (!ISC_IS_FORMAT_RAW(isc->config.sd_format->mbus_code)) { 14091b4e487SEugen Hristev h <<= 1; 14191b4e487SEugen Hristev w <<= 1; 14291b4e487SEugen Hristev } 14391b4e487SEugen Hristev 14491b4e487SEugen Hristev /* 14591b4e487SEugen Hristev * We limit the column/row count that the ISC will output according 14691b4e487SEugen Hristev * to the configured resolution that we want. 14791b4e487SEugen Hristev * This will avoid the situation where the sensor is misconfigured, 14891b4e487SEugen Hristev * sending more data, and the ISC will just take it and DMA to memory, 14991b4e487SEugen Hristev * causing corruption. 15091b4e487SEugen Hristev */ 15191b4e487SEugen Hristev regmap_write(regmap, ISC_PFE_CFG1, 15291b4e487SEugen Hristev (ISC_PFE_CFG1_COLMIN(0) & ISC_PFE_CFG1_COLMIN_MASK) | 15391b4e487SEugen Hristev (ISC_PFE_CFG1_COLMAX(w - 1) & ISC_PFE_CFG1_COLMAX_MASK)); 15491b4e487SEugen Hristev 15591b4e487SEugen Hristev regmap_write(regmap, ISC_PFE_CFG2, 15691b4e487SEugen Hristev (ISC_PFE_CFG2_ROWMIN(0) & ISC_PFE_CFG2_ROWMIN_MASK) | 15791b4e487SEugen Hristev (ISC_PFE_CFG2_ROWMAX(h - 1) & ISC_PFE_CFG2_ROWMAX_MASK)); 15891b4e487SEugen Hristev 15991b4e487SEugen Hristev regmap_update_bits(regmap, ISC_PFE_CFG0, 16091b4e487SEugen Hristev ISC_PFE_CFG0_COLEN | ISC_PFE_CFG0_ROWEN, 16191b4e487SEugen Hristev ISC_PFE_CFG0_COLEN | ISC_PFE_CFG0_ROWEN); 16291b4e487SEugen Hristev } 16391b4e487SEugen Hristev 16491b4e487SEugen Hristev static void isc_start_dma(struct isc_device *isc) 16591b4e487SEugen Hristev { 16691b4e487SEugen Hristev struct regmap *regmap = isc->regmap; 16791b4e487SEugen Hristev u32 sizeimage = isc->fmt.fmt.pix.sizeimage; 16891b4e487SEugen Hristev u32 dctrl_dview; 16991b4e487SEugen Hristev dma_addr_t addr0; 17091b4e487SEugen Hristev 17191b4e487SEugen Hristev addr0 = vb2_dma_contig_plane_dma_addr(&isc->cur_frm->vb.vb2_buf, 0); 17291b4e487SEugen Hristev regmap_write(regmap, ISC_DAD0 + isc->offsets.dma, addr0); 17391b4e487SEugen Hristev 17491b4e487SEugen Hristev switch (isc->config.fourcc) { 17591b4e487SEugen Hristev case V4L2_PIX_FMT_YUV420: 17691b4e487SEugen Hristev regmap_write(regmap, ISC_DAD1 + isc->offsets.dma, 17791b4e487SEugen Hristev addr0 + (sizeimage * 2) / 3); 17891b4e487SEugen Hristev regmap_write(regmap, ISC_DAD2 + isc->offsets.dma, 17991b4e487SEugen Hristev addr0 + (sizeimage * 5) / 6); 18091b4e487SEugen Hristev break; 18191b4e487SEugen Hristev case V4L2_PIX_FMT_YUV422P: 18291b4e487SEugen Hristev regmap_write(regmap, ISC_DAD1 + isc->offsets.dma, 18391b4e487SEugen Hristev addr0 + sizeimage / 2); 18491b4e487SEugen Hristev regmap_write(regmap, ISC_DAD2 + isc->offsets.dma, 18591b4e487SEugen Hristev addr0 + (sizeimage * 3) / 4); 18691b4e487SEugen Hristev break; 18791b4e487SEugen Hristev default: 18891b4e487SEugen Hristev break; 18991b4e487SEugen Hristev } 19091b4e487SEugen Hristev 19191b4e487SEugen Hristev dctrl_dview = isc->config.dctrl_dview; 19291b4e487SEugen Hristev 19391b4e487SEugen Hristev regmap_write(regmap, ISC_DCTRL + isc->offsets.dma, 19491b4e487SEugen Hristev dctrl_dview | ISC_DCTRL_IE_IS); 19591b4e487SEugen Hristev spin_lock(&isc->awb_lock); 19691b4e487SEugen Hristev regmap_write(regmap, ISC_CTRLEN, ISC_CTRL_CAPTURE); 19791b4e487SEugen Hristev spin_unlock(&isc->awb_lock); 19891b4e487SEugen Hristev } 19991b4e487SEugen Hristev 20091b4e487SEugen Hristev static void isc_set_pipeline(struct isc_device *isc, u32 pipeline) 20191b4e487SEugen Hristev { 20291b4e487SEugen Hristev struct regmap *regmap = isc->regmap; 20391b4e487SEugen Hristev struct isc_ctrls *ctrls = &isc->ctrls; 20491b4e487SEugen Hristev u32 val, bay_cfg; 20591b4e487SEugen Hristev const u32 *gamma; 20691b4e487SEugen Hristev unsigned int i; 20791b4e487SEugen Hristev 20891b4e487SEugen Hristev /* WB-->CFA-->CC-->GAM-->CSC-->CBC-->SUB422-->SUB420 */ 20991b4e487SEugen Hristev for (i = 0; i < ISC_PIPE_LINE_NODE_NUM; i++) { 21091b4e487SEugen Hristev val = pipeline & BIT(i) ? 1 : 0; 21191b4e487SEugen Hristev regmap_field_write(isc->pipeline[i], val); 21291b4e487SEugen Hristev } 21391b4e487SEugen Hristev 21491b4e487SEugen Hristev if (!pipeline) 21591b4e487SEugen Hristev return; 21691b4e487SEugen Hristev 21791b4e487SEugen Hristev bay_cfg = isc->config.sd_format->cfa_baycfg; 21891b4e487SEugen Hristev 21991b4e487SEugen Hristev regmap_write(regmap, ISC_WB_CFG, bay_cfg); 22091b4e487SEugen Hristev isc_update_awb_ctrls(isc); 22191b4e487SEugen Hristev isc_update_v4l2_ctrls(isc); 22291b4e487SEugen Hristev 22391b4e487SEugen Hristev regmap_write(regmap, ISC_CFA_CFG, bay_cfg | ISC_CFA_CFG_EITPOL); 22491b4e487SEugen Hristev 22591b4e487SEugen Hristev gamma = &isc->gamma_table[ctrls->gamma_index][0]; 22691b4e487SEugen Hristev regmap_bulk_write(regmap, ISC_GAM_BENTRY, gamma, GAMMA_ENTRIES); 22791b4e487SEugen Hristev regmap_bulk_write(regmap, ISC_GAM_GENTRY, gamma, GAMMA_ENTRIES); 22891b4e487SEugen Hristev regmap_bulk_write(regmap, ISC_GAM_RENTRY, gamma, GAMMA_ENTRIES); 22991b4e487SEugen Hristev 23091b4e487SEugen Hristev isc->config_dpc(isc); 23191b4e487SEugen Hristev isc->config_csc(isc); 23291b4e487SEugen Hristev isc->config_cbc(isc); 23391b4e487SEugen Hristev isc->config_cc(isc); 23491b4e487SEugen Hristev isc->config_gam(isc); 23591b4e487SEugen Hristev } 23691b4e487SEugen Hristev 23791b4e487SEugen Hristev static int isc_update_profile(struct isc_device *isc) 23891b4e487SEugen Hristev { 23991b4e487SEugen Hristev struct regmap *regmap = isc->regmap; 24091b4e487SEugen Hristev u32 sr; 24191b4e487SEugen Hristev int counter = 100; 24291b4e487SEugen Hristev 24391b4e487SEugen Hristev regmap_write(regmap, ISC_CTRLEN, ISC_CTRL_UPPRO); 24491b4e487SEugen Hristev 24591b4e487SEugen Hristev regmap_read(regmap, ISC_CTRLSR, &sr); 24691b4e487SEugen Hristev while ((sr & ISC_CTRL_UPPRO) && counter--) { 24791b4e487SEugen Hristev usleep_range(1000, 2000); 24891b4e487SEugen Hristev regmap_read(regmap, ISC_CTRLSR, &sr); 24991b4e487SEugen Hristev } 25091b4e487SEugen Hristev 25191b4e487SEugen Hristev if (counter < 0) { 25291b4e487SEugen Hristev v4l2_warn(&isc->v4l2_dev, "Time out to update profile\n"); 25391b4e487SEugen Hristev return -ETIMEDOUT; 25491b4e487SEugen Hristev } 25591b4e487SEugen Hristev 25691b4e487SEugen Hristev return 0; 25791b4e487SEugen Hristev } 25891b4e487SEugen Hristev 25991b4e487SEugen Hristev static void isc_set_histogram(struct isc_device *isc, bool enable) 26091b4e487SEugen Hristev { 26191b4e487SEugen Hristev struct regmap *regmap = isc->regmap; 26291b4e487SEugen Hristev struct isc_ctrls *ctrls = &isc->ctrls; 26391b4e487SEugen Hristev 26491b4e487SEugen Hristev if (enable) { 26591b4e487SEugen Hristev regmap_write(regmap, ISC_HIS_CFG + isc->offsets.his, 26691b4e487SEugen Hristev ISC_HIS_CFG_MODE_GR | 26791b4e487SEugen Hristev (isc->config.sd_format->cfa_baycfg 26891b4e487SEugen Hristev << ISC_HIS_CFG_BAYSEL_SHIFT) | 26991b4e487SEugen Hristev ISC_HIS_CFG_RAR); 27091b4e487SEugen Hristev regmap_write(regmap, ISC_HIS_CTRL + isc->offsets.his, 27191b4e487SEugen Hristev ISC_HIS_CTRL_EN); 27291b4e487SEugen Hristev regmap_write(regmap, ISC_INTEN, ISC_INT_HISDONE); 27391b4e487SEugen Hristev ctrls->hist_id = ISC_HIS_CFG_MODE_GR; 27491b4e487SEugen Hristev isc_update_profile(isc); 27591b4e487SEugen Hristev regmap_write(regmap, ISC_CTRLEN, ISC_CTRL_HISREQ); 27691b4e487SEugen Hristev 27791b4e487SEugen Hristev ctrls->hist_stat = HIST_ENABLED; 27891b4e487SEugen Hristev } else { 27991b4e487SEugen Hristev regmap_write(regmap, ISC_INTDIS, ISC_INT_HISDONE); 28091b4e487SEugen Hristev regmap_write(regmap, ISC_HIS_CTRL + isc->offsets.his, 28191b4e487SEugen Hristev ISC_HIS_CTRL_DIS); 28291b4e487SEugen Hristev 28391b4e487SEugen Hristev ctrls->hist_stat = HIST_DISABLED; 28491b4e487SEugen Hristev } 28591b4e487SEugen Hristev } 28691b4e487SEugen Hristev 28791b4e487SEugen Hristev static int isc_configure(struct isc_device *isc) 28891b4e487SEugen Hristev { 28991b4e487SEugen Hristev struct regmap *regmap = isc->regmap; 29091b4e487SEugen Hristev u32 pfe_cfg0, dcfg, mask, pipeline; 29191b4e487SEugen Hristev struct isc_subdev_entity *subdev = isc->current_subdev; 29291b4e487SEugen Hristev 29391b4e487SEugen Hristev pfe_cfg0 = isc->config.sd_format->pfe_cfg0_bps; 29491b4e487SEugen Hristev pipeline = isc->config.bits_pipeline; 29591b4e487SEugen Hristev 29691b4e487SEugen Hristev dcfg = isc->config.dcfg_imode | isc->dcfg; 29791b4e487SEugen Hristev 29891b4e487SEugen Hristev pfe_cfg0 |= subdev->pfe_cfg0 | ISC_PFE_CFG0_MODE_PROGRESSIVE; 29991b4e487SEugen Hristev mask = ISC_PFE_CFG0_BPS_MASK | ISC_PFE_CFG0_HPOL_LOW | 30091b4e487SEugen Hristev ISC_PFE_CFG0_VPOL_LOW | ISC_PFE_CFG0_PPOL_LOW | 30191b4e487SEugen Hristev ISC_PFE_CFG0_MODE_MASK | ISC_PFE_CFG0_CCIR_CRC | 30291b4e487SEugen Hristev ISC_PFE_CFG0_CCIR656 | ISC_PFE_CFG0_MIPI; 30391b4e487SEugen Hristev 30491b4e487SEugen Hristev regmap_update_bits(regmap, ISC_PFE_CFG0, mask, pfe_cfg0); 30591b4e487SEugen Hristev 30691b4e487SEugen Hristev isc->config_rlp(isc); 30791b4e487SEugen Hristev 30891b4e487SEugen Hristev regmap_write(regmap, ISC_DCFG + isc->offsets.dma, dcfg); 30991b4e487SEugen Hristev 31091b4e487SEugen Hristev /* Set the pipeline */ 31191b4e487SEugen Hristev isc_set_pipeline(isc, pipeline); 31291b4e487SEugen Hristev 31391b4e487SEugen Hristev /* 31491b4e487SEugen Hristev * The current implemented histogram is available for RAW R, B, GB, GR 31591b4e487SEugen Hristev * channels. We need to check if sensor is outputting RAW BAYER 31691b4e487SEugen Hristev */ 31791b4e487SEugen Hristev if (isc->ctrls.awb && 31891b4e487SEugen Hristev ISC_IS_FORMAT_RAW(isc->config.sd_format->mbus_code)) 31991b4e487SEugen Hristev isc_set_histogram(isc, true); 32091b4e487SEugen Hristev else 32191b4e487SEugen Hristev isc_set_histogram(isc, false); 32291b4e487SEugen Hristev 32391b4e487SEugen Hristev /* Update profile */ 32491b4e487SEugen Hristev return isc_update_profile(isc); 32591b4e487SEugen Hristev } 32691b4e487SEugen Hristev 3278a8f9cedSEugen Hristev static int isc_prepare_streaming(struct vb2_queue *vq) 3288a8f9cedSEugen Hristev { 3298a8f9cedSEugen Hristev struct isc_device *isc = vb2_get_drv_priv(vq); 3308a8f9cedSEugen Hristev 3318a8f9cedSEugen Hristev return media_pipeline_start(isc->video_dev.entity.pads, &isc->mpipe); 3328a8f9cedSEugen Hristev } 3338a8f9cedSEugen Hristev 33491b4e487SEugen Hristev static int isc_start_streaming(struct vb2_queue *vq, unsigned int count) 33591b4e487SEugen Hristev { 33691b4e487SEugen Hristev struct isc_device *isc = vb2_get_drv_priv(vq); 33791b4e487SEugen Hristev struct regmap *regmap = isc->regmap; 33891b4e487SEugen Hristev struct isc_buffer *buf; 33991b4e487SEugen Hristev unsigned long flags; 34091b4e487SEugen Hristev int ret; 34191b4e487SEugen Hristev 34291b4e487SEugen Hristev /* Enable stream on the sub device */ 34391b4e487SEugen Hristev ret = v4l2_subdev_call(isc->current_subdev->sd, video, s_stream, 1); 34491b4e487SEugen Hristev if (ret && ret != -ENOIOCTLCMD) { 345*8d46c5cdSEugen Hristev dev_err(isc->dev, "stream on failed in subdev %d\n", ret); 34691b4e487SEugen Hristev goto err_start_stream; 34791b4e487SEugen Hristev } 34891b4e487SEugen Hristev 34991b4e487SEugen Hristev ret = pm_runtime_resume_and_get(isc->dev); 35091b4e487SEugen Hristev if (ret < 0) { 351*8d46c5cdSEugen Hristev dev_err(isc->dev, "RPM resume failed in subdev %d\n", 35291b4e487SEugen Hristev ret); 35391b4e487SEugen Hristev goto err_pm_get; 35491b4e487SEugen Hristev } 35591b4e487SEugen Hristev 35691b4e487SEugen Hristev ret = isc_configure(isc); 35791b4e487SEugen Hristev if (unlikely(ret)) 35891b4e487SEugen Hristev goto err_configure; 35991b4e487SEugen Hristev 36091b4e487SEugen Hristev /* Enable DMA interrupt */ 36191b4e487SEugen Hristev regmap_write(regmap, ISC_INTEN, ISC_INT_DDONE); 36291b4e487SEugen Hristev 36391b4e487SEugen Hristev spin_lock_irqsave(&isc->dma_queue_lock, flags); 36491b4e487SEugen Hristev 36591b4e487SEugen Hristev isc->sequence = 0; 36691b4e487SEugen Hristev isc->stop = false; 36791b4e487SEugen Hristev reinit_completion(&isc->comp); 36891b4e487SEugen Hristev 36991b4e487SEugen Hristev isc->cur_frm = list_first_entry(&isc->dma_queue, 37091b4e487SEugen Hristev struct isc_buffer, list); 37191b4e487SEugen Hristev list_del(&isc->cur_frm->list); 37291b4e487SEugen Hristev 37391b4e487SEugen Hristev isc_crop_pfe(isc); 37491b4e487SEugen Hristev isc_start_dma(isc); 37591b4e487SEugen Hristev 37691b4e487SEugen Hristev spin_unlock_irqrestore(&isc->dma_queue_lock, flags); 37791b4e487SEugen Hristev 37891b4e487SEugen Hristev /* if we streaming from RAW, we can do one-shot white balance adj */ 37991b4e487SEugen Hristev if (ISC_IS_FORMAT_RAW(isc->config.sd_format->mbus_code)) 38091b4e487SEugen Hristev v4l2_ctrl_activate(isc->do_wb_ctrl, true); 38191b4e487SEugen Hristev 38291b4e487SEugen Hristev return 0; 38391b4e487SEugen Hristev 38491b4e487SEugen Hristev err_configure: 38591b4e487SEugen Hristev pm_runtime_put_sync(isc->dev); 38691b4e487SEugen Hristev err_pm_get: 38791b4e487SEugen Hristev v4l2_subdev_call(isc->current_subdev->sd, video, s_stream, 0); 38891b4e487SEugen Hristev 38991b4e487SEugen Hristev err_start_stream: 39091b4e487SEugen Hristev spin_lock_irqsave(&isc->dma_queue_lock, flags); 39191b4e487SEugen Hristev list_for_each_entry(buf, &isc->dma_queue, list) 39291b4e487SEugen Hristev vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED); 39391b4e487SEugen Hristev INIT_LIST_HEAD(&isc->dma_queue); 39491b4e487SEugen Hristev spin_unlock_irqrestore(&isc->dma_queue_lock, flags); 39591b4e487SEugen Hristev 39691b4e487SEugen Hristev return ret; 39791b4e487SEugen Hristev } 39891b4e487SEugen Hristev 3998a8f9cedSEugen Hristev static void isc_unprepare_streaming(struct vb2_queue *vq) 4008a8f9cedSEugen Hristev { 4018a8f9cedSEugen Hristev struct isc_device *isc = vb2_get_drv_priv(vq); 4028a8f9cedSEugen Hristev 4038a8f9cedSEugen Hristev /* Stop media pipeline */ 4048a8f9cedSEugen Hristev media_pipeline_stop(isc->video_dev.entity.pads); 4058a8f9cedSEugen Hristev } 4068a8f9cedSEugen Hristev 40791b4e487SEugen Hristev static void isc_stop_streaming(struct vb2_queue *vq) 40891b4e487SEugen Hristev { 40991b4e487SEugen Hristev struct isc_device *isc = vb2_get_drv_priv(vq); 41091b4e487SEugen Hristev unsigned long flags; 41191b4e487SEugen Hristev struct isc_buffer *buf; 41291b4e487SEugen Hristev int ret; 41391b4e487SEugen Hristev 41491b4e487SEugen Hristev mutex_lock(&isc->awb_mutex); 41591b4e487SEugen Hristev v4l2_ctrl_activate(isc->do_wb_ctrl, false); 41691b4e487SEugen Hristev 41791b4e487SEugen Hristev isc->stop = true; 41891b4e487SEugen Hristev 41991b4e487SEugen Hristev /* Wait until the end of the current frame */ 42091b4e487SEugen Hristev if (isc->cur_frm && !wait_for_completion_timeout(&isc->comp, 5 * HZ)) 421*8d46c5cdSEugen Hristev dev_err(isc->dev, "Timeout waiting for end of the capture\n"); 42291b4e487SEugen Hristev 42391b4e487SEugen Hristev mutex_unlock(&isc->awb_mutex); 42491b4e487SEugen Hristev 42591b4e487SEugen Hristev /* Disable DMA interrupt */ 42691b4e487SEugen Hristev regmap_write(isc->regmap, ISC_INTDIS, ISC_INT_DDONE); 42791b4e487SEugen Hristev 42891b4e487SEugen Hristev pm_runtime_put_sync(isc->dev); 42991b4e487SEugen Hristev 43091b4e487SEugen Hristev /* Disable stream on the sub device */ 43191b4e487SEugen Hristev ret = v4l2_subdev_call(isc->current_subdev->sd, video, s_stream, 0); 43291b4e487SEugen Hristev if (ret && ret != -ENOIOCTLCMD) 433*8d46c5cdSEugen Hristev dev_err(isc->dev, "stream off failed in subdev\n"); 43491b4e487SEugen Hristev 43591b4e487SEugen Hristev /* Release all active buffers */ 43691b4e487SEugen Hristev spin_lock_irqsave(&isc->dma_queue_lock, flags); 43791b4e487SEugen Hristev if (unlikely(isc->cur_frm)) { 43891b4e487SEugen Hristev vb2_buffer_done(&isc->cur_frm->vb.vb2_buf, 43991b4e487SEugen Hristev VB2_BUF_STATE_ERROR); 44091b4e487SEugen Hristev isc->cur_frm = NULL; 44191b4e487SEugen Hristev } 44291b4e487SEugen Hristev list_for_each_entry(buf, &isc->dma_queue, list) 44391b4e487SEugen Hristev vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); 44491b4e487SEugen Hristev INIT_LIST_HEAD(&isc->dma_queue); 44591b4e487SEugen Hristev spin_unlock_irqrestore(&isc->dma_queue_lock, flags); 44691b4e487SEugen Hristev } 44791b4e487SEugen Hristev 44891b4e487SEugen Hristev static void isc_buffer_queue(struct vb2_buffer *vb) 44991b4e487SEugen Hristev { 45091b4e487SEugen Hristev struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 45191b4e487SEugen Hristev struct isc_buffer *buf = container_of(vbuf, struct isc_buffer, vb); 45291b4e487SEugen Hristev struct isc_device *isc = vb2_get_drv_priv(vb->vb2_queue); 45391b4e487SEugen Hristev unsigned long flags; 45491b4e487SEugen Hristev 45591b4e487SEugen Hristev spin_lock_irqsave(&isc->dma_queue_lock, flags); 45691b4e487SEugen Hristev if (!isc->cur_frm && list_empty(&isc->dma_queue) && 45791b4e487SEugen Hristev vb2_start_streaming_called(vb->vb2_queue)) { 45891b4e487SEugen Hristev isc->cur_frm = buf; 45991b4e487SEugen Hristev isc_start_dma(isc); 46091b4e487SEugen Hristev } else { 46191b4e487SEugen Hristev list_add_tail(&buf->list, &isc->dma_queue); 46291b4e487SEugen Hristev } 46391b4e487SEugen Hristev spin_unlock_irqrestore(&isc->dma_queue_lock, flags); 46491b4e487SEugen Hristev } 46591b4e487SEugen Hristev 46691b4e487SEugen Hristev static const struct vb2_ops isc_vb2_ops = { 46791b4e487SEugen Hristev .queue_setup = isc_queue_setup, 46891b4e487SEugen Hristev .wait_prepare = vb2_ops_wait_prepare, 46991b4e487SEugen Hristev .wait_finish = vb2_ops_wait_finish, 47091b4e487SEugen Hristev .buf_prepare = isc_buffer_prepare, 47191b4e487SEugen Hristev .start_streaming = isc_start_streaming, 47291b4e487SEugen Hristev .stop_streaming = isc_stop_streaming, 47391b4e487SEugen Hristev .buf_queue = isc_buffer_queue, 4748a8f9cedSEugen Hristev .prepare_streaming = isc_prepare_streaming, 4758a8f9cedSEugen Hristev .unprepare_streaming = isc_unprepare_streaming, 47691b4e487SEugen Hristev }; 47791b4e487SEugen Hristev 47891b4e487SEugen Hristev static int isc_querycap(struct file *file, void *priv, 47991b4e487SEugen Hristev struct v4l2_capability *cap) 48091b4e487SEugen Hristev { 48191b4e487SEugen Hristev struct isc_device *isc = video_drvdata(file); 48291b4e487SEugen Hristev 48391b4e487SEugen Hristev strscpy(cap->driver, "microchip-isc", sizeof(cap->driver)); 48491b4e487SEugen Hristev strscpy(cap->card, "Microchip Image Sensor Controller", sizeof(cap->card)); 48591b4e487SEugen Hristev snprintf(cap->bus_info, sizeof(cap->bus_info), 48691b4e487SEugen Hristev "platform:%s", isc->v4l2_dev.name); 48791b4e487SEugen Hristev 48891b4e487SEugen Hristev return 0; 48991b4e487SEugen Hristev } 49091b4e487SEugen Hristev 49191b4e487SEugen Hristev static int isc_enum_fmt_vid_cap(struct file *file, void *priv, 49291b4e487SEugen Hristev struct v4l2_fmtdesc *f) 49391b4e487SEugen Hristev { 49491b4e487SEugen Hristev struct isc_device *isc = video_drvdata(file); 49591b4e487SEugen Hristev u32 index = f->index; 49678ba0d79SEugen Hristev u32 i, supported_index = 0; 49778ba0d79SEugen Hristev struct isc_format *fmt; 49891b4e487SEugen Hristev 49978ba0d79SEugen Hristev /* 50078ba0d79SEugen Hristev * If we are not asked a specific mbus_code, we have to report all 50178ba0d79SEugen Hristev * the formats that we can output. 50278ba0d79SEugen Hristev */ 50378ba0d79SEugen Hristev if (!f->mbus_code) { 50478ba0d79SEugen Hristev if (index >= isc->controller_formats_size) 50578ba0d79SEugen Hristev return -EINVAL; 50678ba0d79SEugen Hristev 50791b4e487SEugen Hristev f->pixelformat = isc->controller_formats[index].fourcc; 50878ba0d79SEugen Hristev 50991b4e487SEugen Hristev return 0; 51091b4e487SEugen Hristev } 51191b4e487SEugen Hristev 51278ba0d79SEugen Hristev /* 51378ba0d79SEugen Hristev * If a specific mbus_code is requested, check if we support 51478ba0d79SEugen Hristev * this mbus_code as input for the ISC. 51578ba0d79SEugen Hristev * If it's supported, then we report the corresponding pixelformat 51678ba0d79SEugen Hristev * as first possible option for the ISC. 51778ba0d79SEugen Hristev * E.g. mbus MEDIA_BUS_FMT_YUYV8_2X8 and report 51878ba0d79SEugen Hristev * 'YUYV' (YUYV 4:2:2) 51978ba0d79SEugen Hristev */ 52078ba0d79SEugen Hristev fmt = isc_find_format_by_code(isc, f->mbus_code, &i); 52178ba0d79SEugen Hristev if (!fmt) 52278ba0d79SEugen Hristev return -EINVAL; 52391b4e487SEugen Hristev 52478ba0d79SEugen Hristev if (!index) { 52578ba0d79SEugen Hristev f->pixelformat = fmt->fourcc; 52691b4e487SEugen Hristev 52778ba0d79SEugen Hristev return 0; 52878ba0d79SEugen Hristev } 52978ba0d79SEugen Hristev 53078ba0d79SEugen Hristev supported_index++; 53178ba0d79SEugen Hristev 53278ba0d79SEugen Hristev /* If the index is not raw, we don't have anymore formats to report */ 53378ba0d79SEugen Hristev if (!ISC_IS_FORMAT_RAW(f->mbus_code)) 53478ba0d79SEugen Hristev return -EINVAL; 53578ba0d79SEugen Hristev 53678ba0d79SEugen Hristev /* 53778ba0d79SEugen Hristev * We are asked for a specific mbus code, which is raw. 53878ba0d79SEugen Hristev * We have to search through the formats we can convert to. 53978ba0d79SEugen Hristev * We have to skip the raw formats, we cannot convert to raw. 54078ba0d79SEugen Hristev * E.g. 'AR12' (16-bit ARGB 4-4-4-4), 'AR15' (16-bit ARGB 1-5-5-5), etc. 54178ba0d79SEugen Hristev */ 54278ba0d79SEugen Hristev for (i = 0; i < isc->controller_formats_size; i++) { 54378ba0d79SEugen Hristev if (isc->controller_formats[i].raw) 54491b4e487SEugen Hristev continue; 54578ba0d79SEugen Hristev if (index == supported_index) { 54678ba0d79SEugen Hristev f->pixelformat = isc->controller_formats[i].fourcc; 54791b4e487SEugen Hristev return 0; 54891b4e487SEugen Hristev } 54991b4e487SEugen Hristev supported_index++; 55091b4e487SEugen Hristev } 55191b4e487SEugen Hristev 55291b4e487SEugen Hristev return -EINVAL; 55391b4e487SEugen Hristev } 55491b4e487SEugen Hristev 55591b4e487SEugen Hristev static int isc_g_fmt_vid_cap(struct file *file, void *priv, 55691b4e487SEugen Hristev struct v4l2_format *fmt) 55791b4e487SEugen Hristev { 55891b4e487SEugen Hristev struct isc_device *isc = video_drvdata(file); 55991b4e487SEugen Hristev 56091b4e487SEugen Hristev *fmt = isc->fmt; 56191b4e487SEugen Hristev 56291b4e487SEugen Hristev return 0; 56391b4e487SEugen Hristev } 56491b4e487SEugen Hristev 56591b4e487SEugen Hristev /* 56691b4e487SEugen Hristev * Checks the current configured format, if ISC can output it, 56791b4e487SEugen Hristev * considering which type of format the ISC receives from the sensor 56891b4e487SEugen Hristev */ 56991b4e487SEugen Hristev static int isc_try_validate_formats(struct isc_device *isc) 57091b4e487SEugen Hristev { 57191b4e487SEugen Hristev int ret; 57291b4e487SEugen Hristev bool bayer = false, yuv = false, rgb = false, grey = false; 57391b4e487SEugen Hristev 57491b4e487SEugen Hristev /* all formats supported by the RLP module are OK */ 57591b4e487SEugen Hristev switch (isc->try_config.fourcc) { 57691b4e487SEugen Hristev case V4L2_PIX_FMT_SBGGR8: 57791b4e487SEugen Hristev case V4L2_PIX_FMT_SGBRG8: 57891b4e487SEugen Hristev case V4L2_PIX_FMT_SGRBG8: 57991b4e487SEugen Hristev case V4L2_PIX_FMT_SRGGB8: 58091b4e487SEugen Hristev case V4L2_PIX_FMT_SBGGR10: 58191b4e487SEugen Hristev case V4L2_PIX_FMT_SGBRG10: 58291b4e487SEugen Hristev case V4L2_PIX_FMT_SGRBG10: 58391b4e487SEugen Hristev case V4L2_PIX_FMT_SRGGB10: 58491b4e487SEugen Hristev case V4L2_PIX_FMT_SBGGR12: 58591b4e487SEugen Hristev case V4L2_PIX_FMT_SGBRG12: 58691b4e487SEugen Hristev case V4L2_PIX_FMT_SGRBG12: 58791b4e487SEugen Hristev case V4L2_PIX_FMT_SRGGB12: 58891b4e487SEugen Hristev ret = 0; 58991b4e487SEugen Hristev bayer = true; 59091b4e487SEugen Hristev break; 59191b4e487SEugen Hristev 59291b4e487SEugen Hristev case V4L2_PIX_FMT_YUV420: 59391b4e487SEugen Hristev case V4L2_PIX_FMT_YUV422P: 59491b4e487SEugen Hristev case V4L2_PIX_FMT_YUYV: 59591b4e487SEugen Hristev case V4L2_PIX_FMT_UYVY: 59691b4e487SEugen Hristev case V4L2_PIX_FMT_VYUY: 59791b4e487SEugen Hristev ret = 0; 59891b4e487SEugen Hristev yuv = true; 59991b4e487SEugen Hristev break; 60091b4e487SEugen Hristev 60191b4e487SEugen Hristev case V4L2_PIX_FMT_RGB565: 60291b4e487SEugen Hristev case V4L2_PIX_FMT_ABGR32: 60391b4e487SEugen Hristev case V4L2_PIX_FMT_XBGR32: 60491b4e487SEugen Hristev case V4L2_PIX_FMT_ARGB444: 60591b4e487SEugen Hristev case V4L2_PIX_FMT_ARGB555: 60691b4e487SEugen Hristev ret = 0; 60791b4e487SEugen Hristev rgb = true; 60891b4e487SEugen Hristev break; 60991b4e487SEugen Hristev case V4L2_PIX_FMT_GREY: 61091b4e487SEugen Hristev case V4L2_PIX_FMT_Y10: 61191b4e487SEugen Hristev case V4L2_PIX_FMT_Y16: 61291b4e487SEugen Hristev ret = 0; 61391b4e487SEugen Hristev grey = true; 61491b4e487SEugen Hristev break; 61591b4e487SEugen Hristev default: 61691b4e487SEugen Hristev /* any other different formats are not supported */ 617*8d46c5cdSEugen Hristev dev_err(isc->dev, "Requested unsupported format.\n"); 61891b4e487SEugen Hristev ret = -EINVAL; 61991b4e487SEugen Hristev } 620*8d46c5cdSEugen Hristev dev_dbg(isc->dev, 62191b4e487SEugen Hristev "Format validation, requested rgb=%u, yuv=%u, grey=%u, bayer=%u\n", 62291b4e487SEugen Hristev rgb, yuv, grey, bayer); 62391b4e487SEugen Hristev 62478ba0d79SEugen Hristev if (bayer && 62578ba0d79SEugen Hristev !ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code)) { 626*8d46c5cdSEugen Hristev dev_err(isc->dev, "Cannot output RAW if we do not receive RAW.\n"); 62791b4e487SEugen Hristev return -EINVAL; 62878ba0d79SEugen Hristev } 62991b4e487SEugen Hristev 63091b4e487SEugen Hristev if (grey && !ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code) && 63178ba0d79SEugen Hristev !ISC_IS_FORMAT_GREY(isc->try_config.sd_format->mbus_code)) { 632*8d46c5cdSEugen Hristev dev_err(isc->dev, "Cannot output GREY if we do not receive RAW/GREY.\n"); 63391b4e487SEugen Hristev return -EINVAL; 63478ba0d79SEugen Hristev } 63578ba0d79SEugen Hristev 63678ba0d79SEugen Hristev if ((rgb || bayer || yuv) && 63778ba0d79SEugen Hristev ISC_IS_FORMAT_GREY(isc->try_config.sd_format->mbus_code)) { 638*8d46c5cdSEugen Hristev dev_err(isc->dev, "Cannot convert GREY to another format.\n"); 63978ba0d79SEugen Hristev return -EINVAL; 64078ba0d79SEugen Hristev } 64191b4e487SEugen Hristev 64291b4e487SEugen Hristev return ret; 64391b4e487SEugen Hristev } 64491b4e487SEugen Hristev 64591b4e487SEugen Hristev /* 64691b4e487SEugen Hristev * Configures the RLP and DMA modules, depending on the output format 64791b4e487SEugen Hristev * configured for the ISC. 64891b4e487SEugen Hristev * If direct_dump == true, just dump raw data 8/16 bits depending on format. 64991b4e487SEugen Hristev */ 65091b4e487SEugen Hristev static int isc_try_configure_rlp_dma(struct isc_device *isc, bool direct_dump) 65191b4e487SEugen Hristev { 65291b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = 0; 65391b4e487SEugen Hristev 65491b4e487SEugen Hristev switch (isc->try_config.fourcc) { 65591b4e487SEugen Hristev case V4L2_PIX_FMT_SBGGR8: 65691b4e487SEugen Hristev case V4L2_PIX_FMT_SGBRG8: 65791b4e487SEugen Hristev case V4L2_PIX_FMT_SGRBG8: 65891b4e487SEugen Hristev case V4L2_PIX_FMT_SRGGB8: 65991b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT8; 66091b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED8; 66191b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; 66291b4e487SEugen Hristev isc->try_config.bpp = 8; 66391b4e487SEugen Hristev isc->try_config.bpp_v4l2 = 8; 66491b4e487SEugen Hristev break; 66591b4e487SEugen Hristev case V4L2_PIX_FMT_SBGGR10: 66691b4e487SEugen Hristev case V4L2_PIX_FMT_SGBRG10: 66791b4e487SEugen Hristev case V4L2_PIX_FMT_SGRBG10: 66891b4e487SEugen Hristev case V4L2_PIX_FMT_SRGGB10: 66991b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT10; 67091b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED16; 67191b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; 67291b4e487SEugen Hristev isc->try_config.bpp = 16; 67391b4e487SEugen Hristev isc->try_config.bpp_v4l2 = 16; 67491b4e487SEugen Hristev break; 67591b4e487SEugen Hristev case V4L2_PIX_FMT_SBGGR12: 67691b4e487SEugen Hristev case V4L2_PIX_FMT_SGBRG12: 67791b4e487SEugen Hristev case V4L2_PIX_FMT_SGRBG12: 67891b4e487SEugen Hristev case V4L2_PIX_FMT_SRGGB12: 67991b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT12; 68091b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED16; 68191b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; 68291b4e487SEugen Hristev isc->try_config.bpp = 16; 68391b4e487SEugen Hristev isc->try_config.bpp_v4l2 = 16; 68491b4e487SEugen Hristev break; 68591b4e487SEugen Hristev case V4L2_PIX_FMT_RGB565: 68691b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_RGB565; 68791b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED16; 68891b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; 68991b4e487SEugen Hristev isc->try_config.bpp = 16; 69091b4e487SEugen Hristev isc->try_config.bpp_v4l2 = 16; 69191b4e487SEugen Hristev break; 69291b4e487SEugen Hristev case V4L2_PIX_FMT_ARGB444: 69391b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_ARGB444; 69491b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED16; 69591b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; 69691b4e487SEugen Hristev isc->try_config.bpp = 16; 69791b4e487SEugen Hristev isc->try_config.bpp_v4l2 = 16; 69891b4e487SEugen Hristev break; 69991b4e487SEugen Hristev case V4L2_PIX_FMT_ARGB555: 70091b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_ARGB555; 70191b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED16; 70291b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; 70391b4e487SEugen Hristev isc->try_config.bpp = 16; 70491b4e487SEugen Hristev isc->try_config.bpp_v4l2 = 16; 70591b4e487SEugen Hristev break; 70691b4e487SEugen Hristev case V4L2_PIX_FMT_ABGR32: 70791b4e487SEugen Hristev case V4L2_PIX_FMT_XBGR32: 70891b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_ARGB32; 70991b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED32; 71091b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; 71191b4e487SEugen Hristev isc->try_config.bpp = 32; 71291b4e487SEugen Hristev isc->try_config.bpp_v4l2 = 32; 71391b4e487SEugen Hristev break; 71491b4e487SEugen Hristev case V4L2_PIX_FMT_YUV420: 71591b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_YYCC; 71691b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_YC420P; 71791b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PLANAR; 71891b4e487SEugen Hristev isc->try_config.bpp = 12; 71991b4e487SEugen Hristev isc->try_config.bpp_v4l2 = 8; /* only first plane */ 72091b4e487SEugen Hristev break; 72191b4e487SEugen Hristev case V4L2_PIX_FMT_YUV422P: 72291b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_YYCC; 72391b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_YC422P; 72491b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PLANAR; 72591b4e487SEugen Hristev isc->try_config.bpp = 16; 72691b4e487SEugen Hristev isc->try_config.bpp_v4l2 = 8; /* only first plane */ 72791b4e487SEugen Hristev break; 72891b4e487SEugen Hristev case V4L2_PIX_FMT_YUYV: 72991b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_YCYC | ISC_RLP_CFG_YMODE_YUYV; 73091b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED32; 73191b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; 73291b4e487SEugen Hristev isc->try_config.bpp = 16; 73391b4e487SEugen Hristev isc->try_config.bpp_v4l2 = 16; 73491b4e487SEugen Hristev break; 73591b4e487SEugen Hristev case V4L2_PIX_FMT_UYVY: 73691b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_YCYC | ISC_RLP_CFG_YMODE_UYVY; 73791b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED32; 73891b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; 73991b4e487SEugen Hristev isc->try_config.bpp = 16; 74091b4e487SEugen Hristev isc->try_config.bpp_v4l2 = 16; 74191b4e487SEugen Hristev break; 74291b4e487SEugen Hristev case V4L2_PIX_FMT_VYUY: 74391b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_YCYC | ISC_RLP_CFG_YMODE_VYUY; 74491b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED32; 74591b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; 74691b4e487SEugen Hristev isc->try_config.bpp = 16; 74791b4e487SEugen Hristev isc->try_config.bpp_v4l2 = 16; 74891b4e487SEugen Hristev break; 74991b4e487SEugen Hristev case V4L2_PIX_FMT_GREY: 75091b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_DATY8; 75191b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED8; 75291b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; 75391b4e487SEugen Hristev isc->try_config.bpp = 8; 75491b4e487SEugen Hristev isc->try_config.bpp_v4l2 = 8; 75591b4e487SEugen Hristev break; 75691b4e487SEugen Hristev case V4L2_PIX_FMT_Y16: 75791b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_DATY10 | ISC_RLP_CFG_LSH; 75891b4e487SEugen Hristev fallthrough; 75991b4e487SEugen Hristev case V4L2_PIX_FMT_Y10: 76091b4e487SEugen Hristev isc->try_config.rlp_cfg_mode |= ISC_RLP_CFG_MODE_DATY10; 76191b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED16; 76291b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; 76391b4e487SEugen Hristev isc->try_config.bpp = 16; 76491b4e487SEugen Hristev isc->try_config.bpp_v4l2 = 16; 76591b4e487SEugen Hristev break; 76691b4e487SEugen Hristev default: 76791b4e487SEugen Hristev return -EINVAL; 76891b4e487SEugen Hristev } 76991b4e487SEugen Hristev 77091b4e487SEugen Hristev if (direct_dump) { 77191b4e487SEugen Hristev isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT8; 77291b4e487SEugen Hristev isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED8; 77391b4e487SEugen Hristev isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; 77491b4e487SEugen Hristev return 0; 77591b4e487SEugen Hristev } 77691b4e487SEugen Hristev 77791b4e487SEugen Hristev return 0; 77891b4e487SEugen Hristev } 77991b4e487SEugen Hristev 78091b4e487SEugen Hristev /* 78191b4e487SEugen Hristev * Configuring pipeline modules, depending on which format the ISC outputs 78291b4e487SEugen Hristev * and considering which format it has as input from the sensor. 78391b4e487SEugen Hristev */ 78491b4e487SEugen Hristev static int isc_try_configure_pipeline(struct isc_device *isc) 78591b4e487SEugen Hristev { 78691b4e487SEugen Hristev switch (isc->try_config.fourcc) { 78791b4e487SEugen Hristev case V4L2_PIX_FMT_RGB565: 78891b4e487SEugen Hristev case V4L2_PIX_FMT_ARGB555: 78991b4e487SEugen Hristev case V4L2_PIX_FMT_ARGB444: 79091b4e487SEugen Hristev case V4L2_PIX_FMT_ABGR32: 79191b4e487SEugen Hristev case V4L2_PIX_FMT_XBGR32: 79291b4e487SEugen Hristev /* if sensor format is RAW, we convert inside ISC */ 79391b4e487SEugen Hristev if (ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code)) { 79491b4e487SEugen Hristev isc->try_config.bits_pipeline = CFA_ENABLE | 79591b4e487SEugen Hristev WB_ENABLE | GAM_ENABLES | DPC_BLCENABLE | 79691b4e487SEugen Hristev CC_ENABLE; 79791b4e487SEugen Hristev } else { 79891b4e487SEugen Hristev isc->try_config.bits_pipeline = 0x0; 79991b4e487SEugen Hristev } 80091b4e487SEugen Hristev break; 80191b4e487SEugen Hristev case V4L2_PIX_FMT_YUV420: 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 | GAM_ENABLES | WB_ENABLE | 80691b4e487SEugen Hristev SUB420_ENABLE | SUB422_ENABLE | CBC_ENABLE | 80791b4e487SEugen Hristev DPC_BLCENABLE; 80891b4e487SEugen Hristev } else { 80991b4e487SEugen Hristev isc->try_config.bits_pipeline = 0x0; 81091b4e487SEugen Hristev } 81191b4e487SEugen Hristev break; 81291b4e487SEugen Hristev case V4L2_PIX_FMT_YUV422P: 81391b4e487SEugen Hristev /* if sensor format is RAW, we convert inside ISC */ 81491b4e487SEugen Hristev if (ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code)) { 81591b4e487SEugen Hristev isc->try_config.bits_pipeline = CFA_ENABLE | 81691b4e487SEugen Hristev CSC_ENABLE | WB_ENABLE | GAM_ENABLES | 81791b4e487SEugen Hristev SUB422_ENABLE | CBC_ENABLE | DPC_BLCENABLE; 81891b4e487SEugen Hristev } else { 81991b4e487SEugen Hristev isc->try_config.bits_pipeline = 0x0; 82091b4e487SEugen Hristev } 82191b4e487SEugen Hristev break; 82291b4e487SEugen Hristev case V4L2_PIX_FMT_YUYV: 82391b4e487SEugen Hristev case V4L2_PIX_FMT_UYVY: 82491b4e487SEugen Hristev case V4L2_PIX_FMT_VYUY: 82591b4e487SEugen Hristev /* if sensor format is RAW, we convert inside ISC */ 82691b4e487SEugen Hristev if (ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code)) { 82791b4e487SEugen Hristev isc->try_config.bits_pipeline = CFA_ENABLE | 82891b4e487SEugen Hristev CSC_ENABLE | WB_ENABLE | GAM_ENABLES | 82991b4e487SEugen Hristev SUB422_ENABLE | CBC_ENABLE | DPC_BLCENABLE; 83091b4e487SEugen Hristev } else { 83191b4e487SEugen Hristev isc->try_config.bits_pipeline = 0x0; 83291b4e487SEugen Hristev } 83391b4e487SEugen Hristev break; 83491b4e487SEugen Hristev case V4L2_PIX_FMT_GREY: 83591b4e487SEugen Hristev case V4L2_PIX_FMT_Y16: 83691b4e487SEugen Hristev /* if sensor format is RAW, we convert inside ISC */ 83791b4e487SEugen Hristev if (ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code)) { 83891b4e487SEugen Hristev isc->try_config.bits_pipeline = CFA_ENABLE | 83991b4e487SEugen Hristev CSC_ENABLE | WB_ENABLE | GAM_ENABLES | 84091b4e487SEugen Hristev CBC_ENABLE | DPC_BLCENABLE; 84191b4e487SEugen Hristev } else { 84291b4e487SEugen Hristev isc->try_config.bits_pipeline = 0x0; 84391b4e487SEugen Hristev } 84491b4e487SEugen Hristev break; 84591b4e487SEugen Hristev default: 84691b4e487SEugen Hristev if (ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code)) 84791b4e487SEugen Hristev isc->try_config.bits_pipeline = WB_ENABLE | DPC_BLCENABLE; 84891b4e487SEugen Hristev else 84991b4e487SEugen Hristev isc->try_config.bits_pipeline = 0x0; 85091b4e487SEugen Hristev } 85191b4e487SEugen Hristev 85291b4e487SEugen Hristev /* Tune the pipeline to product specific */ 85391b4e487SEugen Hristev isc->adapt_pipeline(isc); 85491b4e487SEugen Hristev 85591b4e487SEugen Hristev return 0; 85691b4e487SEugen Hristev } 85791b4e487SEugen Hristev 85891b4e487SEugen Hristev static void isc_try_fse(struct isc_device *isc, 85991b4e487SEugen Hristev struct v4l2_subdev_state *sd_state) 86091b4e487SEugen Hristev { 86191b4e487SEugen Hristev int ret; 86291b4e487SEugen Hristev struct v4l2_subdev_frame_size_enum fse = {}; 86391b4e487SEugen Hristev 86491b4e487SEugen Hristev /* 86591b4e487SEugen Hristev * If we do not know yet which format the subdev is using, we cannot 86691b4e487SEugen Hristev * do anything. 86791b4e487SEugen Hristev */ 86878ba0d79SEugen Hristev if (!isc->config.sd_format) 86991b4e487SEugen Hristev return; 87091b4e487SEugen Hristev 87191b4e487SEugen Hristev fse.code = isc->try_config.sd_format->mbus_code; 87291b4e487SEugen Hristev fse.which = V4L2_SUBDEV_FORMAT_TRY; 87391b4e487SEugen Hristev 87491b4e487SEugen Hristev ret = v4l2_subdev_call(isc->current_subdev->sd, pad, enum_frame_size, 87591b4e487SEugen Hristev sd_state, &fse); 87691b4e487SEugen Hristev /* 87791b4e487SEugen Hristev * Attempt to obtain format size from subdev. If not available, 87891b4e487SEugen Hristev * just use the maximum ISC can receive. 87991b4e487SEugen Hristev */ 88091b4e487SEugen Hristev if (ret) { 88191b4e487SEugen Hristev sd_state->pads->try_crop.width = isc->max_width; 88291b4e487SEugen Hristev sd_state->pads->try_crop.height = isc->max_height; 88391b4e487SEugen Hristev } else { 88491b4e487SEugen Hristev sd_state->pads->try_crop.width = fse.max_width; 88591b4e487SEugen Hristev sd_state->pads->try_crop.height = fse.max_height; 88691b4e487SEugen Hristev } 88791b4e487SEugen Hristev } 88891b4e487SEugen Hristev 88978ba0d79SEugen Hristev static int isc_try_fmt(struct isc_device *isc, struct v4l2_format *f) 89091b4e487SEugen Hristev { 89191b4e487SEugen Hristev struct v4l2_pix_format *pixfmt = &f->fmt.pix; 89278ba0d79SEugen Hristev unsigned int i; 89391b4e487SEugen Hristev 89491b4e487SEugen Hristev if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 89591b4e487SEugen Hristev return -EINVAL; 89691b4e487SEugen Hristev 89778ba0d79SEugen Hristev isc->try_config.fourcc = isc->controller_formats[0].fourcc; 89878ba0d79SEugen Hristev 89978ba0d79SEugen Hristev /* find if the format requested is supported */ 90078ba0d79SEugen Hristev for (i = 0; i < isc->controller_formats_size; i++) 90178ba0d79SEugen Hristev if (isc->controller_formats[i].fourcc == pixfmt->pixelformat) { 90278ba0d79SEugen Hristev isc->try_config.fourcc = pixfmt->pixelformat; 90391b4e487SEugen Hristev break; 90491b4e487SEugen Hristev } 90591b4e487SEugen Hristev 90678ba0d79SEugen Hristev isc_try_configure_rlp_dma(isc, false); 90791b4e487SEugen Hristev 90891b4e487SEugen Hristev /* Limit to Microchip ISC hardware capabilities */ 90978ba0d79SEugen Hristev v4l_bound_align_image(&pixfmt->width, 16, isc->max_width, 0, 91078ba0d79SEugen Hristev &pixfmt->height, 16, isc->max_height, 0, 0); 91178ba0d79SEugen Hristev /* If we did not find the requested format, we will fallback here */ 91278ba0d79SEugen Hristev pixfmt->pixelformat = isc->try_config.fourcc; 91378ba0d79SEugen Hristev pixfmt->colorspace = V4L2_COLORSPACE_SRGB; 91491b4e487SEugen Hristev pixfmt->field = V4L2_FIELD_NONE; 91578ba0d79SEugen Hristev 91691b4e487SEugen Hristev pixfmt->bytesperline = (pixfmt->width * isc->try_config.bpp_v4l2) >> 3; 91791b4e487SEugen Hristev pixfmt->sizeimage = ((pixfmt->width * isc->try_config.bpp) >> 3) * 91891b4e487SEugen Hristev pixfmt->height; 91991b4e487SEugen Hristev 92078ba0d79SEugen Hristev isc->try_fmt = *f; 92191b4e487SEugen Hristev 92291b4e487SEugen Hristev return 0; 92391b4e487SEugen Hristev } 92491b4e487SEugen Hristev 92591b4e487SEugen Hristev static int isc_set_fmt(struct isc_device *isc, struct v4l2_format *f) 92691b4e487SEugen Hristev { 92778ba0d79SEugen Hristev isc_try_fmt(isc, f); 92878ba0d79SEugen Hristev 92978ba0d79SEugen Hristev /* make the try configuration active */ 93078ba0d79SEugen Hristev isc->config = isc->try_config; 93178ba0d79SEugen Hristev isc->fmt = isc->try_fmt; 93278ba0d79SEugen Hristev 933*8d46c5cdSEugen Hristev dev_dbg(isc->dev, "ISC set_fmt to %.4s @%dx%d\n", 93478ba0d79SEugen Hristev (char *)&f->fmt.pix.pixelformat, 93578ba0d79SEugen Hristev f->fmt.pix.width, f->fmt.pix.height); 93678ba0d79SEugen Hristev 93778ba0d79SEugen Hristev return 0; 93878ba0d79SEugen Hristev } 93978ba0d79SEugen Hristev 94078ba0d79SEugen Hristev static int isc_validate(struct isc_device *isc) 94178ba0d79SEugen Hristev { 94278ba0d79SEugen Hristev int ret; 94378ba0d79SEugen Hristev int i; 94478ba0d79SEugen Hristev struct isc_format *sd_fmt = NULL; 94578ba0d79SEugen Hristev struct v4l2_pix_format *pixfmt = &isc->fmt.fmt.pix; 94691b4e487SEugen Hristev struct v4l2_subdev_format format = { 94791b4e487SEugen Hristev .which = V4L2_SUBDEV_FORMAT_ACTIVE, 94878ba0d79SEugen Hristev .pad = isc->remote_pad, 94991b4e487SEugen Hristev }; 95078ba0d79SEugen Hristev struct v4l2_subdev_pad_config pad_cfg = {}; 95178ba0d79SEugen Hristev struct v4l2_subdev_state pad_state = { 95278ba0d79SEugen Hristev .pads = &pad_cfg, 95378ba0d79SEugen Hristev }; 95491b4e487SEugen Hristev 95578ba0d79SEugen Hristev /* Get current format from subdev */ 95678ba0d79SEugen Hristev ret = v4l2_subdev_call(isc->current_subdev->sd, pad, get_fmt, NULL, 95778ba0d79SEugen Hristev &format); 95891b4e487SEugen Hristev if (ret) 95991b4e487SEugen Hristev return ret; 96091b4e487SEugen Hristev 96178ba0d79SEugen Hristev /* Identify the subdev's format configuration */ 96278ba0d79SEugen Hristev for (i = 0; i < isc->formats_list_size; i++) 96378ba0d79SEugen Hristev if (isc->formats_list[i].mbus_code == format.format.code) { 96478ba0d79SEugen Hristev sd_fmt = &isc->formats_list[i]; 96578ba0d79SEugen Hristev break; 96678ba0d79SEugen Hristev } 96778ba0d79SEugen Hristev 96878ba0d79SEugen Hristev /* Check if the format is not supported */ 96978ba0d79SEugen Hristev if (!sd_fmt) { 970*8d46c5cdSEugen Hristev dev_err(isc->dev, 97178ba0d79SEugen Hristev "Current subdevice is streaming a media bus code that is not supported 0x%x\n", 97278ba0d79SEugen Hristev format.format.code); 97378ba0d79SEugen Hristev return -EPIPE; 97478ba0d79SEugen Hristev } 97578ba0d79SEugen Hristev 97678ba0d79SEugen Hristev /* At this moment we know which format the subdev will use */ 97778ba0d79SEugen Hristev isc->try_config.sd_format = sd_fmt; 97878ba0d79SEugen Hristev 97978ba0d79SEugen Hristev /* If the sensor is not RAW, we can only do a direct dump */ 98078ba0d79SEugen Hristev if (!ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code)) 98178ba0d79SEugen Hristev isc_try_configure_rlp_dma(isc, true); 98291b4e487SEugen Hristev 98391b4e487SEugen Hristev /* Limit to Microchip ISC hardware capabilities */ 98478ba0d79SEugen Hristev v4l_bound_align_image(&format.format.width, 16, isc->max_width, 0, 98578ba0d79SEugen Hristev &format.format.height, 16, isc->max_height, 0, 0); 98691b4e487SEugen Hristev 98778ba0d79SEugen Hristev /* Check if the frame size is the same. Otherwise we may overflow */ 98878ba0d79SEugen Hristev if (pixfmt->height != format.format.height || 98978ba0d79SEugen Hristev pixfmt->width != format.format.width) { 990*8d46c5cdSEugen Hristev dev_err(isc->dev, 99178ba0d79SEugen Hristev "ISC not configured with the proper frame size: %dx%d\n", 99278ba0d79SEugen Hristev format.format.width, format.format.height); 99378ba0d79SEugen Hristev return -EPIPE; 99478ba0d79SEugen Hristev } 99591b4e487SEugen Hristev 996*8d46c5cdSEugen Hristev dev_dbg(isc->dev, 99778ba0d79SEugen Hristev "Identified subdev using format %.4s with %dx%d %d bpp\n", 99878ba0d79SEugen Hristev (char *)&sd_fmt->fourcc, pixfmt->width, pixfmt->height, 99978ba0d79SEugen Hristev isc->try_config.bpp); 100078ba0d79SEugen Hristev 100178ba0d79SEugen Hristev /* Reset and restart AWB if the subdevice changed the format */ 100291b4e487SEugen Hristev if (isc->try_config.sd_format && isc->config.sd_format && 100391b4e487SEugen Hristev isc->try_config.sd_format != isc->config.sd_format) { 100491b4e487SEugen Hristev isc->ctrls.hist_stat = HIST_INIT; 100591b4e487SEugen Hristev isc_reset_awb_ctrls(isc); 100691b4e487SEugen Hristev isc_update_v4l2_ctrls(isc); 100791b4e487SEugen Hristev } 100878ba0d79SEugen Hristev 100978ba0d79SEugen Hristev /* Validate formats */ 101078ba0d79SEugen Hristev ret = isc_try_validate_formats(isc); 101178ba0d79SEugen Hristev if (ret) 101278ba0d79SEugen Hristev return ret; 101378ba0d79SEugen Hristev 101478ba0d79SEugen Hristev /* Obtain frame sizes if possible to have crop requirements ready */ 101578ba0d79SEugen Hristev isc_try_fse(isc, &pad_state); 101678ba0d79SEugen Hristev 101778ba0d79SEugen Hristev /* Configure ISC pipeline for the config */ 101878ba0d79SEugen Hristev ret = isc_try_configure_pipeline(isc); 101978ba0d79SEugen Hristev if (ret) 102078ba0d79SEugen Hristev return ret; 102178ba0d79SEugen Hristev 102291b4e487SEugen Hristev isc->config = isc->try_config; 102391b4e487SEugen Hristev 1024*8d46c5cdSEugen Hristev dev_dbg(isc->dev, "New ISC configuration in place\n"); 102591b4e487SEugen Hristev 102691b4e487SEugen Hristev return 0; 102791b4e487SEugen Hristev } 102891b4e487SEugen Hristev 102991b4e487SEugen Hristev static int isc_s_fmt_vid_cap(struct file *file, void *priv, 103091b4e487SEugen Hristev struct v4l2_format *f) 103191b4e487SEugen Hristev { 103291b4e487SEugen Hristev struct isc_device *isc = video_drvdata(file); 103391b4e487SEugen Hristev 103491b4e487SEugen Hristev if (vb2_is_busy(&isc->vb2_vidq)) 103591b4e487SEugen Hristev return -EBUSY; 103691b4e487SEugen Hristev 103791b4e487SEugen Hristev return isc_set_fmt(isc, f); 103891b4e487SEugen Hristev } 103991b4e487SEugen Hristev 104091b4e487SEugen Hristev static int isc_try_fmt_vid_cap(struct file *file, void *priv, 104191b4e487SEugen Hristev struct v4l2_format *f) 104291b4e487SEugen Hristev { 104391b4e487SEugen Hristev struct isc_device *isc = video_drvdata(file); 104491b4e487SEugen Hristev 104578ba0d79SEugen Hristev return isc_try_fmt(isc, f); 104691b4e487SEugen Hristev } 104791b4e487SEugen Hristev 104891b4e487SEugen Hristev static int isc_enum_input(struct file *file, void *priv, 104991b4e487SEugen Hristev struct v4l2_input *inp) 105091b4e487SEugen Hristev { 105191b4e487SEugen Hristev if (inp->index != 0) 105291b4e487SEugen Hristev return -EINVAL; 105391b4e487SEugen Hristev 105491b4e487SEugen Hristev inp->type = V4L2_INPUT_TYPE_CAMERA; 105591b4e487SEugen Hristev inp->std = 0; 105691b4e487SEugen Hristev strscpy(inp->name, "Camera", sizeof(inp->name)); 105791b4e487SEugen Hristev 105891b4e487SEugen Hristev return 0; 105991b4e487SEugen Hristev } 106091b4e487SEugen Hristev 106191b4e487SEugen Hristev static int isc_g_input(struct file *file, void *priv, unsigned int *i) 106291b4e487SEugen Hristev { 106391b4e487SEugen Hristev *i = 0; 106491b4e487SEugen Hristev 106591b4e487SEugen Hristev return 0; 106691b4e487SEugen Hristev } 106791b4e487SEugen Hristev 106891b4e487SEugen Hristev static int isc_s_input(struct file *file, void *priv, unsigned int i) 106991b4e487SEugen Hristev { 107091b4e487SEugen Hristev if (i > 0) 107191b4e487SEugen Hristev return -EINVAL; 107291b4e487SEugen Hristev 107391b4e487SEugen Hristev return 0; 107491b4e487SEugen Hristev } 107591b4e487SEugen Hristev 107691b4e487SEugen Hristev static int isc_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a) 107791b4e487SEugen Hristev { 107891b4e487SEugen Hristev struct isc_device *isc = video_drvdata(file); 107991b4e487SEugen Hristev 108091b4e487SEugen Hristev return v4l2_g_parm_cap(video_devdata(file), isc->current_subdev->sd, a); 108191b4e487SEugen Hristev } 108291b4e487SEugen Hristev 108391b4e487SEugen Hristev static int isc_s_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_s_parm_cap(video_devdata(file), isc->current_subdev->sd, a); 108891b4e487SEugen Hristev } 108991b4e487SEugen Hristev 109091b4e487SEugen Hristev static int isc_enum_framesizes(struct file *file, void *fh, 109191b4e487SEugen Hristev struct v4l2_frmsizeenum *fsize) 109291b4e487SEugen Hristev { 109391b4e487SEugen Hristev struct isc_device *isc = video_drvdata(file); 109491b4e487SEugen Hristev int ret = -EINVAL; 109591b4e487SEugen Hristev int i; 109691b4e487SEugen Hristev 109791b4e487SEugen Hristev if (fsize->index) 109891b4e487SEugen Hristev return -EINVAL; 109991b4e487SEugen Hristev 110091b4e487SEugen Hristev for (i = 0; i < isc->controller_formats_size; i++) 110191b4e487SEugen Hristev if (isc->controller_formats[i].fourcc == fsize->pixel_format) 110291b4e487SEugen Hristev ret = 0; 110391b4e487SEugen Hristev 110491b4e487SEugen Hristev if (ret) 110591b4e487SEugen Hristev return ret; 110691b4e487SEugen Hristev 110791b4e487SEugen Hristev fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS; 110891b4e487SEugen Hristev 110991b4e487SEugen Hristev fsize->stepwise.min_width = 16; 111091b4e487SEugen Hristev fsize->stepwise.max_width = isc->max_width; 111191b4e487SEugen Hristev fsize->stepwise.min_height = 16; 111291b4e487SEugen Hristev fsize->stepwise.max_height = isc->max_height; 111391b4e487SEugen Hristev fsize->stepwise.step_width = 1; 111491b4e487SEugen Hristev fsize->stepwise.step_height = 1; 111591b4e487SEugen Hristev 111691b4e487SEugen Hristev return 0; 111791b4e487SEugen Hristev } 111891b4e487SEugen Hristev 111991b4e487SEugen Hristev static const struct v4l2_ioctl_ops isc_ioctl_ops = { 112091b4e487SEugen Hristev .vidioc_querycap = isc_querycap, 112191b4e487SEugen Hristev .vidioc_enum_fmt_vid_cap = isc_enum_fmt_vid_cap, 112291b4e487SEugen Hristev .vidioc_g_fmt_vid_cap = isc_g_fmt_vid_cap, 112391b4e487SEugen Hristev .vidioc_s_fmt_vid_cap = isc_s_fmt_vid_cap, 112491b4e487SEugen Hristev .vidioc_try_fmt_vid_cap = isc_try_fmt_vid_cap, 112591b4e487SEugen Hristev 112691b4e487SEugen Hristev .vidioc_enum_input = isc_enum_input, 112791b4e487SEugen Hristev .vidioc_g_input = isc_g_input, 112891b4e487SEugen Hristev .vidioc_s_input = isc_s_input, 112991b4e487SEugen Hristev 113091b4e487SEugen Hristev .vidioc_reqbufs = vb2_ioctl_reqbufs, 113191b4e487SEugen Hristev .vidioc_querybuf = vb2_ioctl_querybuf, 113291b4e487SEugen Hristev .vidioc_qbuf = vb2_ioctl_qbuf, 113391b4e487SEugen Hristev .vidioc_expbuf = vb2_ioctl_expbuf, 113491b4e487SEugen Hristev .vidioc_dqbuf = vb2_ioctl_dqbuf, 113591b4e487SEugen Hristev .vidioc_create_bufs = vb2_ioctl_create_bufs, 113691b4e487SEugen Hristev .vidioc_prepare_buf = vb2_ioctl_prepare_buf, 113791b4e487SEugen Hristev .vidioc_streamon = vb2_ioctl_streamon, 113891b4e487SEugen Hristev .vidioc_streamoff = vb2_ioctl_streamoff, 113991b4e487SEugen Hristev 114091b4e487SEugen Hristev .vidioc_g_parm = isc_g_parm, 114191b4e487SEugen Hristev .vidioc_s_parm = isc_s_parm, 114291b4e487SEugen Hristev .vidioc_enum_framesizes = isc_enum_framesizes, 114391b4e487SEugen Hristev 114491b4e487SEugen Hristev .vidioc_log_status = v4l2_ctrl_log_status, 114591b4e487SEugen Hristev .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, 114691b4e487SEugen Hristev .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 114791b4e487SEugen Hristev }; 114891b4e487SEugen Hristev 114991b4e487SEugen Hristev static int isc_open(struct file *file) 115091b4e487SEugen Hristev { 115191b4e487SEugen Hristev struct isc_device *isc = video_drvdata(file); 115291b4e487SEugen Hristev struct v4l2_subdev *sd = isc->current_subdev->sd; 115391b4e487SEugen Hristev int ret; 115491b4e487SEugen Hristev 115591b4e487SEugen Hristev if (mutex_lock_interruptible(&isc->lock)) 115691b4e487SEugen Hristev return -ERESTARTSYS; 115791b4e487SEugen Hristev 115891b4e487SEugen Hristev ret = v4l2_fh_open(file); 115991b4e487SEugen Hristev if (ret < 0) 116091b4e487SEugen Hristev goto unlock; 116191b4e487SEugen Hristev 116291b4e487SEugen Hristev if (!v4l2_fh_is_singular_file(file)) 116391b4e487SEugen Hristev goto unlock; 116491b4e487SEugen Hristev 116591b4e487SEugen Hristev ret = v4l2_subdev_call(sd, core, s_power, 1); 116691b4e487SEugen Hristev if (ret < 0 && ret != -ENOIOCTLCMD) { 116791b4e487SEugen Hristev v4l2_fh_release(file); 116891b4e487SEugen Hristev goto unlock; 116991b4e487SEugen Hristev } 117091b4e487SEugen Hristev 117191b4e487SEugen Hristev ret = isc_set_fmt(isc, &isc->fmt); 117291b4e487SEugen Hristev if (ret) { 117391b4e487SEugen Hristev v4l2_subdev_call(sd, core, s_power, 0); 117491b4e487SEugen Hristev v4l2_fh_release(file); 117591b4e487SEugen Hristev } 117691b4e487SEugen Hristev 117791b4e487SEugen Hristev unlock: 117891b4e487SEugen Hristev mutex_unlock(&isc->lock); 117991b4e487SEugen Hristev return ret; 118091b4e487SEugen Hristev } 118191b4e487SEugen Hristev 118291b4e487SEugen Hristev static int isc_release(struct file *file) 118391b4e487SEugen Hristev { 118491b4e487SEugen Hristev struct isc_device *isc = video_drvdata(file); 118591b4e487SEugen Hristev struct v4l2_subdev *sd = isc->current_subdev->sd; 118691b4e487SEugen Hristev bool fh_singular; 118791b4e487SEugen Hristev int ret; 118891b4e487SEugen Hristev 118991b4e487SEugen Hristev mutex_lock(&isc->lock); 119091b4e487SEugen Hristev 119191b4e487SEugen Hristev fh_singular = v4l2_fh_is_singular_file(file); 119291b4e487SEugen Hristev 119391b4e487SEugen Hristev ret = _vb2_fop_release(file, NULL); 119491b4e487SEugen Hristev 119591b4e487SEugen Hristev if (fh_singular) 119691b4e487SEugen Hristev v4l2_subdev_call(sd, core, s_power, 0); 119791b4e487SEugen Hristev 119891b4e487SEugen Hristev mutex_unlock(&isc->lock); 119991b4e487SEugen Hristev 120091b4e487SEugen Hristev return ret; 120191b4e487SEugen Hristev } 120291b4e487SEugen Hristev 120391b4e487SEugen Hristev static const struct v4l2_file_operations isc_fops = { 120491b4e487SEugen Hristev .owner = THIS_MODULE, 120591b4e487SEugen Hristev .open = isc_open, 120691b4e487SEugen Hristev .release = isc_release, 120791b4e487SEugen Hristev .unlocked_ioctl = video_ioctl2, 120891b4e487SEugen Hristev .read = vb2_fop_read, 120991b4e487SEugen Hristev .mmap = vb2_fop_mmap, 121091b4e487SEugen Hristev .poll = vb2_fop_poll, 121191b4e487SEugen Hristev }; 121291b4e487SEugen Hristev 121391b4e487SEugen Hristev irqreturn_t microchip_isc_interrupt(int irq, void *dev_id) 121491b4e487SEugen Hristev { 121591b4e487SEugen Hristev struct isc_device *isc = (struct isc_device *)dev_id; 121691b4e487SEugen Hristev struct regmap *regmap = isc->regmap; 121791b4e487SEugen Hristev u32 isc_intsr, isc_intmask, pending; 121891b4e487SEugen Hristev irqreturn_t ret = IRQ_NONE; 121991b4e487SEugen Hristev 122091b4e487SEugen Hristev regmap_read(regmap, ISC_INTSR, &isc_intsr); 122191b4e487SEugen Hristev regmap_read(regmap, ISC_INTMASK, &isc_intmask); 122291b4e487SEugen Hristev 122391b4e487SEugen Hristev pending = isc_intsr & isc_intmask; 122491b4e487SEugen Hristev 122591b4e487SEugen Hristev if (likely(pending & ISC_INT_DDONE)) { 122691b4e487SEugen Hristev spin_lock(&isc->dma_queue_lock); 122791b4e487SEugen Hristev if (isc->cur_frm) { 122891b4e487SEugen Hristev struct vb2_v4l2_buffer *vbuf = &isc->cur_frm->vb; 122991b4e487SEugen Hristev struct vb2_buffer *vb = &vbuf->vb2_buf; 123091b4e487SEugen Hristev 123191b4e487SEugen Hristev vb->timestamp = ktime_get_ns(); 123291b4e487SEugen Hristev vbuf->sequence = isc->sequence++; 123391b4e487SEugen Hristev vb2_buffer_done(vb, VB2_BUF_STATE_DONE); 123491b4e487SEugen Hristev isc->cur_frm = NULL; 123591b4e487SEugen Hristev } 123691b4e487SEugen Hristev 123791b4e487SEugen Hristev if (!list_empty(&isc->dma_queue) && !isc->stop) { 123891b4e487SEugen Hristev isc->cur_frm = list_first_entry(&isc->dma_queue, 123991b4e487SEugen Hristev struct isc_buffer, list); 124091b4e487SEugen Hristev list_del(&isc->cur_frm->list); 124191b4e487SEugen Hristev 124291b4e487SEugen Hristev isc_start_dma(isc); 124391b4e487SEugen Hristev } 124491b4e487SEugen Hristev 124591b4e487SEugen Hristev if (isc->stop) 124691b4e487SEugen Hristev complete(&isc->comp); 124791b4e487SEugen Hristev 124891b4e487SEugen Hristev ret = IRQ_HANDLED; 124991b4e487SEugen Hristev spin_unlock(&isc->dma_queue_lock); 125091b4e487SEugen Hristev } 125191b4e487SEugen Hristev 125291b4e487SEugen Hristev if (pending & ISC_INT_HISDONE) { 125391b4e487SEugen Hristev schedule_work(&isc->awb_work); 125491b4e487SEugen Hristev ret = IRQ_HANDLED; 125591b4e487SEugen Hristev } 125691b4e487SEugen Hristev 125791b4e487SEugen Hristev return ret; 125891b4e487SEugen Hristev } 125991b4e487SEugen Hristev EXPORT_SYMBOL_GPL(microchip_isc_interrupt); 126091b4e487SEugen Hristev 126191b4e487SEugen Hristev static void isc_hist_count(struct isc_device *isc, u32 *min, u32 *max) 126291b4e487SEugen Hristev { 126391b4e487SEugen Hristev struct regmap *regmap = isc->regmap; 126491b4e487SEugen Hristev struct isc_ctrls *ctrls = &isc->ctrls; 126591b4e487SEugen Hristev u32 *hist_count = &ctrls->hist_count[ctrls->hist_id]; 126691b4e487SEugen Hristev u32 *hist_entry = &ctrls->hist_entry[0]; 126791b4e487SEugen Hristev u32 i; 126891b4e487SEugen Hristev 126991b4e487SEugen Hristev *min = 0; 127091b4e487SEugen Hristev *max = HIST_ENTRIES; 127191b4e487SEugen Hristev 127291b4e487SEugen Hristev regmap_bulk_read(regmap, ISC_HIS_ENTRY + isc->offsets.his_entry, 127391b4e487SEugen Hristev hist_entry, HIST_ENTRIES); 127491b4e487SEugen Hristev 127591b4e487SEugen Hristev *hist_count = 0; 127691b4e487SEugen Hristev /* 127791b4e487SEugen Hristev * we deliberately ignore the end of the histogram, 127891b4e487SEugen Hristev * the most white pixels 127991b4e487SEugen Hristev */ 128091b4e487SEugen Hristev for (i = 1; i < HIST_ENTRIES; i++) { 128191b4e487SEugen Hristev if (*hist_entry && !*min) 128291b4e487SEugen Hristev *min = i; 128391b4e487SEugen Hristev if (*hist_entry) 128491b4e487SEugen Hristev *max = i; 128591b4e487SEugen Hristev *hist_count += i * (*hist_entry++); 128691b4e487SEugen Hristev } 128791b4e487SEugen Hristev 128891b4e487SEugen Hristev if (!*min) 128991b4e487SEugen Hristev *min = 1; 129091b4e487SEugen Hristev 1291*8d46c5cdSEugen Hristev dev_dbg(isc->dev, "isc wb: hist_id %u, hist_count %u", 129291b4e487SEugen Hristev ctrls->hist_id, *hist_count); 129391b4e487SEugen Hristev } 129491b4e487SEugen Hristev 129591b4e487SEugen Hristev static void isc_wb_update(struct isc_ctrls *ctrls) 129691b4e487SEugen Hristev { 129791b4e487SEugen Hristev struct isc_device *isc = container_of(ctrls, struct isc_device, ctrls); 129891b4e487SEugen Hristev u32 *hist_count = &ctrls->hist_count[0]; 129991b4e487SEugen Hristev u32 c, offset[4]; 130091b4e487SEugen Hristev u64 avg = 0; 130191b4e487SEugen Hristev /* We compute two gains, stretch gain and grey world gain */ 130291b4e487SEugen Hristev u32 s_gain[4], gw_gain[4]; 130391b4e487SEugen Hristev 130491b4e487SEugen Hristev /* 130591b4e487SEugen Hristev * According to Grey World, we need to set gains for R/B to normalize 130691b4e487SEugen Hristev * them towards the green channel. 130791b4e487SEugen Hristev * Thus we want to keep Green as fixed and adjust only Red/Blue 130891b4e487SEugen Hristev * Compute the average of the both green channels first 130991b4e487SEugen Hristev */ 131091b4e487SEugen Hristev avg = (u64)hist_count[ISC_HIS_CFG_MODE_GR] + 131191b4e487SEugen Hristev (u64)hist_count[ISC_HIS_CFG_MODE_GB]; 131291b4e487SEugen Hristev avg >>= 1; 131391b4e487SEugen Hristev 1314*8d46c5cdSEugen Hristev dev_dbg(isc->dev, "isc wb: green components average %llu\n", avg); 131591b4e487SEugen Hristev 131691b4e487SEugen Hristev /* Green histogram is null, nothing to do */ 131791b4e487SEugen Hristev if (!avg) 131891b4e487SEugen Hristev return; 131991b4e487SEugen Hristev 132091b4e487SEugen Hristev for (c = ISC_HIS_CFG_MODE_GR; c <= ISC_HIS_CFG_MODE_B; c++) { 132191b4e487SEugen Hristev /* 132291b4e487SEugen Hristev * the color offset is the minimum value of the histogram. 132391b4e487SEugen Hristev * we stretch this color to the full range by substracting 132491b4e487SEugen Hristev * this value from the color component. 132591b4e487SEugen Hristev */ 132691b4e487SEugen Hristev offset[c] = ctrls->hist_minmax[c][HIST_MIN_INDEX]; 132791b4e487SEugen Hristev /* 132891b4e487SEugen Hristev * The offset is always at least 1. If the offset is 1, we do 132991b4e487SEugen Hristev * not need to adjust it, so our result must be zero. 133091b4e487SEugen Hristev * the offset is computed in a histogram on 9 bits (0..512) 133191b4e487SEugen Hristev * but the offset in register is based on 133291b4e487SEugen Hristev * 12 bits pipeline (0..4096). 133391b4e487SEugen Hristev * we need to shift with the 3 bits that the histogram is 133491b4e487SEugen Hristev * ignoring 133591b4e487SEugen Hristev */ 133691b4e487SEugen Hristev ctrls->offset[c] = (offset[c] - 1) << 3; 133791b4e487SEugen Hristev 133891b4e487SEugen Hristev /* 133991b4e487SEugen Hristev * the offset is then taken and converted to 2's complements, 134091b4e487SEugen Hristev * and must be negative, as we subtract this value from the 134191b4e487SEugen Hristev * color components 134291b4e487SEugen Hristev */ 134391b4e487SEugen Hristev ctrls->offset[c] = -ctrls->offset[c]; 134491b4e487SEugen Hristev 134591b4e487SEugen Hristev /* 134691b4e487SEugen Hristev * the stretch gain is the total number of histogram bins 134791b4e487SEugen Hristev * divided by the actual range of color component (Max - Min) 134891b4e487SEugen Hristev * If we compute gain like this, the actual color component 134991b4e487SEugen Hristev * will be stretched to the full histogram. 135091b4e487SEugen Hristev * We need to shift 9 bits for precision, we have 9 bits for 135191b4e487SEugen Hristev * decimals 135291b4e487SEugen Hristev */ 135391b4e487SEugen Hristev s_gain[c] = (HIST_ENTRIES << 9) / 135491b4e487SEugen Hristev (ctrls->hist_minmax[c][HIST_MAX_INDEX] - 135591b4e487SEugen Hristev ctrls->hist_minmax[c][HIST_MIN_INDEX] + 1); 135691b4e487SEugen Hristev 135791b4e487SEugen Hristev /* 135891b4e487SEugen Hristev * Now we have to compute the gain w.r.t. the average. 135991b4e487SEugen Hristev * Add/lose gain to the component towards the average. 136091b4e487SEugen Hristev * If it happens that the component is zero, use the 136191b4e487SEugen Hristev * fixed point value : 1.0 gain. 136291b4e487SEugen Hristev */ 136391b4e487SEugen Hristev if (hist_count[c]) 136491b4e487SEugen Hristev gw_gain[c] = div_u64(avg << 9, hist_count[c]); 136591b4e487SEugen Hristev else 136691b4e487SEugen Hristev gw_gain[c] = 1 << 9; 136791b4e487SEugen Hristev 1368*8d46c5cdSEugen Hristev dev_dbg(isc->dev, 136991b4e487SEugen Hristev "isc wb: component %d, s_gain %u, gw_gain %u\n", 137091b4e487SEugen Hristev c, s_gain[c], gw_gain[c]); 137191b4e487SEugen Hristev /* multiply both gains and adjust for decimals */ 137291b4e487SEugen Hristev ctrls->gain[c] = s_gain[c] * gw_gain[c]; 137391b4e487SEugen Hristev ctrls->gain[c] >>= 9; 137491b4e487SEugen Hristev 137591b4e487SEugen Hristev /* make sure we are not out of range */ 137691b4e487SEugen Hristev ctrls->gain[c] = clamp_val(ctrls->gain[c], 0, GENMASK(12, 0)); 137791b4e487SEugen Hristev 1378*8d46c5cdSEugen Hristev dev_dbg(isc->dev, "isc wb: component %d, final gain %u\n", 137991b4e487SEugen Hristev c, ctrls->gain[c]); 138091b4e487SEugen Hristev } 138191b4e487SEugen Hristev } 138291b4e487SEugen Hristev 138391b4e487SEugen Hristev static void isc_awb_work(struct work_struct *w) 138491b4e487SEugen Hristev { 138591b4e487SEugen Hristev struct isc_device *isc = 138691b4e487SEugen Hristev container_of(w, struct isc_device, awb_work); 138791b4e487SEugen Hristev struct regmap *regmap = isc->regmap; 138891b4e487SEugen Hristev struct isc_ctrls *ctrls = &isc->ctrls; 138991b4e487SEugen Hristev u32 hist_id = ctrls->hist_id; 139091b4e487SEugen Hristev u32 baysel; 139191b4e487SEugen Hristev unsigned long flags; 139291b4e487SEugen Hristev u32 min, max; 139391b4e487SEugen Hristev int ret; 139491b4e487SEugen Hristev 139591b4e487SEugen Hristev if (ctrls->hist_stat != HIST_ENABLED) 139691b4e487SEugen Hristev return; 139791b4e487SEugen Hristev 139891b4e487SEugen Hristev isc_hist_count(isc, &min, &max); 139991b4e487SEugen Hristev 1400*8d46c5cdSEugen Hristev dev_dbg(isc->dev, 140191b4e487SEugen Hristev "isc wb mode %d: hist min %u , max %u\n", hist_id, min, max); 140291b4e487SEugen Hristev 140391b4e487SEugen Hristev ctrls->hist_minmax[hist_id][HIST_MIN_INDEX] = min; 140491b4e487SEugen Hristev ctrls->hist_minmax[hist_id][HIST_MAX_INDEX] = max; 140591b4e487SEugen Hristev 140691b4e487SEugen Hristev if (hist_id != ISC_HIS_CFG_MODE_B) { 140791b4e487SEugen Hristev hist_id++; 140891b4e487SEugen Hristev } else { 140991b4e487SEugen Hristev isc_wb_update(ctrls); 141091b4e487SEugen Hristev hist_id = ISC_HIS_CFG_MODE_GR; 141191b4e487SEugen Hristev } 141291b4e487SEugen Hristev 141391b4e487SEugen Hristev ctrls->hist_id = hist_id; 141491b4e487SEugen Hristev baysel = isc->config.sd_format->cfa_baycfg << ISC_HIS_CFG_BAYSEL_SHIFT; 141591b4e487SEugen Hristev 141691b4e487SEugen Hristev ret = pm_runtime_resume_and_get(isc->dev); 141791b4e487SEugen Hristev if (ret < 0) 141891b4e487SEugen Hristev return; 141991b4e487SEugen Hristev 142091b4e487SEugen Hristev /* 142191b4e487SEugen Hristev * only update if we have all the required histograms and controls 142291b4e487SEugen Hristev * if awb has been disabled, we need to reset registers as well. 142391b4e487SEugen Hristev */ 142491b4e487SEugen Hristev if (hist_id == ISC_HIS_CFG_MODE_GR || ctrls->awb == ISC_WB_NONE) { 142591b4e487SEugen Hristev /* 142691b4e487SEugen Hristev * It may happen that DMA Done IRQ will trigger while we are 142791b4e487SEugen Hristev * updating white balance registers here. 142891b4e487SEugen Hristev * In that case, only parts of the controls have been updated. 142991b4e487SEugen Hristev * We can avoid that by locking the section. 143091b4e487SEugen Hristev */ 143191b4e487SEugen Hristev spin_lock_irqsave(&isc->awb_lock, flags); 143291b4e487SEugen Hristev isc_update_awb_ctrls(isc); 143391b4e487SEugen Hristev spin_unlock_irqrestore(&isc->awb_lock, flags); 143491b4e487SEugen Hristev 143591b4e487SEugen Hristev /* 143691b4e487SEugen Hristev * if we are doing just the one time white balance adjustment, 143791b4e487SEugen Hristev * we are basically done. 143891b4e487SEugen Hristev */ 143991b4e487SEugen Hristev if (ctrls->awb == ISC_WB_ONETIME) { 1440*8d46c5cdSEugen Hristev dev_info(isc->dev, 144191b4e487SEugen Hristev "Completed one time white-balance adjustment.\n"); 144291b4e487SEugen Hristev /* update the v4l2 controls values */ 144391b4e487SEugen Hristev isc_update_v4l2_ctrls(isc); 144491b4e487SEugen Hristev ctrls->awb = ISC_WB_NONE; 144591b4e487SEugen Hristev } 144691b4e487SEugen Hristev } 144791b4e487SEugen Hristev regmap_write(regmap, ISC_HIS_CFG + isc->offsets.his, 144891b4e487SEugen Hristev hist_id | baysel | ISC_HIS_CFG_RAR); 144991b4e487SEugen Hristev 145091b4e487SEugen Hristev /* 145191b4e487SEugen Hristev * We have to make sure the streaming has not stopped meanwhile. 145291b4e487SEugen Hristev * ISC requires a frame to clock the internal profile update. 145391b4e487SEugen Hristev * To avoid issues, lock the sequence with a mutex 145491b4e487SEugen Hristev */ 145591b4e487SEugen Hristev mutex_lock(&isc->awb_mutex); 145691b4e487SEugen Hristev 145791b4e487SEugen Hristev /* streaming is not active anymore */ 145891b4e487SEugen Hristev if (isc->stop) { 145991b4e487SEugen Hristev mutex_unlock(&isc->awb_mutex); 146091b4e487SEugen Hristev return; 146191b4e487SEugen Hristev } 146291b4e487SEugen Hristev 146391b4e487SEugen Hristev isc_update_profile(isc); 146491b4e487SEugen Hristev 146591b4e487SEugen Hristev mutex_unlock(&isc->awb_mutex); 146691b4e487SEugen Hristev 146791b4e487SEugen Hristev /* if awb has been disabled, we don't need to start another histogram */ 146891b4e487SEugen Hristev if (ctrls->awb) 146991b4e487SEugen Hristev regmap_write(regmap, ISC_CTRLEN, ISC_CTRL_HISREQ); 147091b4e487SEugen Hristev 147191b4e487SEugen Hristev pm_runtime_put_sync(isc->dev); 147291b4e487SEugen Hristev } 147391b4e487SEugen Hristev 147491b4e487SEugen Hristev static int isc_s_ctrl(struct v4l2_ctrl *ctrl) 147591b4e487SEugen Hristev { 147691b4e487SEugen Hristev struct isc_device *isc = container_of(ctrl->handler, 147791b4e487SEugen Hristev struct isc_device, ctrls.handler); 147891b4e487SEugen Hristev struct isc_ctrls *ctrls = &isc->ctrls; 147991b4e487SEugen Hristev 148091b4e487SEugen Hristev if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE) 148191b4e487SEugen Hristev return 0; 148291b4e487SEugen Hristev 148391b4e487SEugen Hristev switch (ctrl->id) { 148491b4e487SEugen Hristev case V4L2_CID_BRIGHTNESS: 148591b4e487SEugen Hristev ctrls->brightness = ctrl->val & ISC_CBC_BRIGHT_MASK; 148691b4e487SEugen Hristev break; 148791b4e487SEugen Hristev case V4L2_CID_CONTRAST: 148891b4e487SEugen Hristev ctrls->contrast = ctrl->val & ISC_CBC_CONTRAST_MASK; 148991b4e487SEugen Hristev break; 149091b4e487SEugen Hristev case V4L2_CID_GAMMA: 149191b4e487SEugen Hristev ctrls->gamma_index = ctrl->val; 149291b4e487SEugen Hristev break; 149391b4e487SEugen Hristev default: 149491b4e487SEugen Hristev return -EINVAL; 149591b4e487SEugen Hristev } 149691b4e487SEugen Hristev 149791b4e487SEugen Hristev return 0; 149891b4e487SEugen Hristev } 149991b4e487SEugen Hristev 150091b4e487SEugen Hristev static const struct v4l2_ctrl_ops isc_ctrl_ops = { 150191b4e487SEugen Hristev .s_ctrl = isc_s_ctrl, 150291b4e487SEugen Hristev }; 150391b4e487SEugen Hristev 150491b4e487SEugen Hristev static int isc_s_awb_ctrl(struct v4l2_ctrl *ctrl) 150591b4e487SEugen Hristev { 150691b4e487SEugen Hristev struct isc_device *isc = container_of(ctrl->handler, 150791b4e487SEugen Hristev struct isc_device, ctrls.handler); 150891b4e487SEugen Hristev struct isc_ctrls *ctrls = &isc->ctrls; 150991b4e487SEugen Hristev 151091b4e487SEugen Hristev if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE) 151191b4e487SEugen Hristev return 0; 151291b4e487SEugen Hristev 151391b4e487SEugen Hristev switch (ctrl->id) { 151491b4e487SEugen Hristev case V4L2_CID_AUTO_WHITE_BALANCE: 151591b4e487SEugen Hristev if (ctrl->val == 1) 151691b4e487SEugen Hristev ctrls->awb = ISC_WB_AUTO; 151791b4e487SEugen Hristev else 151891b4e487SEugen Hristev ctrls->awb = ISC_WB_NONE; 151991b4e487SEugen Hristev 152091b4e487SEugen Hristev /* configure the controls with new values from v4l2 */ 152191b4e487SEugen Hristev if (ctrl->cluster[ISC_CTRL_R_GAIN]->is_new) 152291b4e487SEugen Hristev ctrls->gain[ISC_HIS_CFG_MODE_R] = isc->r_gain_ctrl->val; 152391b4e487SEugen Hristev if (ctrl->cluster[ISC_CTRL_B_GAIN]->is_new) 152491b4e487SEugen Hristev ctrls->gain[ISC_HIS_CFG_MODE_B] = isc->b_gain_ctrl->val; 152591b4e487SEugen Hristev if (ctrl->cluster[ISC_CTRL_GR_GAIN]->is_new) 152691b4e487SEugen Hristev ctrls->gain[ISC_HIS_CFG_MODE_GR] = isc->gr_gain_ctrl->val; 152791b4e487SEugen Hristev if (ctrl->cluster[ISC_CTRL_GB_GAIN]->is_new) 152891b4e487SEugen Hristev ctrls->gain[ISC_HIS_CFG_MODE_GB] = isc->gb_gain_ctrl->val; 152991b4e487SEugen Hristev 153091b4e487SEugen Hristev if (ctrl->cluster[ISC_CTRL_R_OFF]->is_new) 153191b4e487SEugen Hristev ctrls->offset[ISC_HIS_CFG_MODE_R] = isc->r_off_ctrl->val; 153291b4e487SEugen Hristev if (ctrl->cluster[ISC_CTRL_B_OFF]->is_new) 153391b4e487SEugen Hristev ctrls->offset[ISC_HIS_CFG_MODE_B] = isc->b_off_ctrl->val; 153491b4e487SEugen Hristev if (ctrl->cluster[ISC_CTRL_GR_OFF]->is_new) 153591b4e487SEugen Hristev ctrls->offset[ISC_HIS_CFG_MODE_GR] = isc->gr_off_ctrl->val; 153691b4e487SEugen Hristev if (ctrl->cluster[ISC_CTRL_GB_OFF]->is_new) 153791b4e487SEugen Hristev ctrls->offset[ISC_HIS_CFG_MODE_GB] = isc->gb_off_ctrl->val; 153891b4e487SEugen Hristev 153991b4e487SEugen Hristev isc_update_awb_ctrls(isc); 154091b4e487SEugen Hristev 154191b4e487SEugen Hristev mutex_lock(&isc->awb_mutex); 154291b4e487SEugen Hristev if (vb2_is_streaming(&isc->vb2_vidq)) { 154391b4e487SEugen Hristev /* 154491b4e487SEugen Hristev * If we are streaming, we can update profile to 154591b4e487SEugen Hristev * have the new settings in place. 154691b4e487SEugen Hristev */ 154791b4e487SEugen Hristev isc_update_profile(isc); 154891b4e487SEugen Hristev } else { 154991b4e487SEugen Hristev /* 155091b4e487SEugen Hristev * The auto cluster will activate automatically this 155191b4e487SEugen Hristev * control. This has to be deactivated when not 155291b4e487SEugen Hristev * streaming. 155391b4e487SEugen Hristev */ 155491b4e487SEugen Hristev v4l2_ctrl_activate(isc->do_wb_ctrl, false); 155591b4e487SEugen Hristev } 155691b4e487SEugen Hristev mutex_unlock(&isc->awb_mutex); 155791b4e487SEugen Hristev 155891b4e487SEugen Hristev /* if we have autowhitebalance on, start histogram procedure */ 155991b4e487SEugen Hristev if (ctrls->awb == ISC_WB_AUTO && 156091b4e487SEugen Hristev vb2_is_streaming(&isc->vb2_vidq) && 156191b4e487SEugen Hristev ISC_IS_FORMAT_RAW(isc->config.sd_format->mbus_code)) 156291b4e487SEugen Hristev isc_set_histogram(isc, true); 156391b4e487SEugen Hristev 156491b4e487SEugen Hristev /* 156591b4e487SEugen Hristev * for one time whitebalance adjustment, check the button, 156691b4e487SEugen Hristev * if it's pressed, perform the one time operation. 156791b4e487SEugen Hristev */ 156891b4e487SEugen Hristev if (ctrls->awb == ISC_WB_NONE && 156991b4e487SEugen Hristev ctrl->cluster[ISC_CTRL_DO_WB]->is_new && 157091b4e487SEugen Hristev !(ctrl->cluster[ISC_CTRL_DO_WB]->flags & 157191b4e487SEugen Hristev V4L2_CTRL_FLAG_INACTIVE)) { 157291b4e487SEugen Hristev ctrls->awb = ISC_WB_ONETIME; 157391b4e487SEugen Hristev isc_set_histogram(isc, true); 1574*8d46c5cdSEugen Hristev dev_dbg(isc->dev, "One time white-balance started.\n"); 157591b4e487SEugen Hristev } 157691b4e487SEugen Hristev return 0; 157791b4e487SEugen Hristev } 157891b4e487SEugen Hristev return 0; 157991b4e487SEugen Hristev } 158091b4e487SEugen Hristev 158191b4e487SEugen Hristev static int isc_g_volatile_awb_ctrl(struct v4l2_ctrl *ctrl) 158291b4e487SEugen Hristev { 158391b4e487SEugen Hristev struct isc_device *isc = container_of(ctrl->handler, 158491b4e487SEugen Hristev struct isc_device, ctrls.handler); 158591b4e487SEugen Hristev struct isc_ctrls *ctrls = &isc->ctrls; 158691b4e487SEugen Hristev 158791b4e487SEugen Hristev switch (ctrl->id) { 158891b4e487SEugen Hristev /* being a cluster, this id will be called for every control */ 158991b4e487SEugen Hristev case V4L2_CID_AUTO_WHITE_BALANCE: 159091b4e487SEugen Hristev ctrl->cluster[ISC_CTRL_R_GAIN]->val = 159191b4e487SEugen Hristev ctrls->gain[ISC_HIS_CFG_MODE_R]; 159291b4e487SEugen Hristev ctrl->cluster[ISC_CTRL_B_GAIN]->val = 159391b4e487SEugen Hristev ctrls->gain[ISC_HIS_CFG_MODE_B]; 159491b4e487SEugen Hristev ctrl->cluster[ISC_CTRL_GR_GAIN]->val = 159591b4e487SEugen Hristev ctrls->gain[ISC_HIS_CFG_MODE_GR]; 159691b4e487SEugen Hristev ctrl->cluster[ISC_CTRL_GB_GAIN]->val = 159791b4e487SEugen Hristev ctrls->gain[ISC_HIS_CFG_MODE_GB]; 159891b4e487SEugen Hristev 159991b4e487SEugen Hristev ctrl->cluster[ISC_CTRL_R_OFF]->val = 160091b4e487SEugen Hristev ctrls->offset[ISC_HIS_CFG_MODE_R]; 160191b4e487SEugen Hristev ctrl->cluster[ISC_CTRL_B_OFF]->val = 160291b4e487SEugen Hristev ctrls->offset[ISC_HIS_CFG_MODE_B]; 160391b4e487SEugen Hristev ctrl->cluster[ISC_CTRL_GR_OFF]->val = 160491b4e487SEugen Hristev ctrls->offset[ISC_HIS_CFG_MODE_GR]; 160591b4e487SEugen Hristev ctrl->cluster[ISC_CTRL_GB_OFF]->val = 160691b4e487SEugen Hristev ctrls->offset[ISC_HIS_CFG_MODE_GB]; 160791b4e487SEugen Hristev break; 160891b4e487SEugen Hristev } 160991b4e487SEugen Hristev return 0; 161091b4e487SEugen Hristev } 161191b4e487SEugen Hristev 161291b4e487SEugen Hristev static const struct v4l2_ctrl_ops isc_awb_ops = { 161391b4e487SEugen Hristev .s_ctrl = isc_s_awb_ctrl, 161491b4e487SEugen Hristev .g_volatile_ctrl = isc_g_volatile_awb_ctrl, 161591b4e487SEugen Hristev }; 161691b4e487SEugen Hristev 161791b4e487SEugen Hristev #define ISC_CTRL_OFF(_name, _id, _name_str) \ 161891b4e487SEugen Hristev static const struct v4l2_ctrl_config _name = { \ 161991b4e487SEugen Hristev .ops = &isc_awb_ops, \ 162091b4e487SEugen Hristev .id = _id, \ 162191b4e487SEugen Hristev .name = _name_str, \ 162291b4e487SEugen Hristev .type = V4L2_CTRL_TYPE_INTEGER, \ 162391b4e487SEugen Hristev .flags = V4L2_CTRL_FLAG_SLIDER, \ 162491b4e487SEugen Hristev .min = -4095, \ 162591b4e487SEugen Hristev .max = 4095, \ 162691b4e487SEugen Hristev .step = 1, \ 162791b4e487SEugen Hristev .def = 0, \ 162891b4e487SEugen Hristev } 162991b4e487SEugen Hristev 163091b4e487SEugen Hristev ISC_CTRL_OFF(isc_r_off_ctrl, ISC_CID_R_OFFSET, "Red Component Offset"); 163191b4e487SEugen Hristev ISC_CTRL_OFF(isc_b_off_ctrl, ISC_CID_B_OFFSET, "Blue Component Offset"); 163291b4e487SEugen Hristev ISC_CTRL_OFF(isc_gr_off_ctrl, ISC_CID_GR_OFFSET, "Green Red Component Offset"); 163391b4e487SEugen Hristev ISC_CTRL_OFF(isc_gb_off_ctrl, ISC_CID_GB_OFFSET, "Green Blue Component Offset"); 163491b4e487SEugen Hristev 163591b4e487SEugen Hristev #define ISC_CTRL_GAIN(_name, _id, _name_str) \ 163691b4e487SEugen Hristev static const struct v4l2_ctrl_config _name = { \ 163791b4e487SEugen Hristev .ops = &isc_awb_ops, \ 163891b4e487SEugen Hristev .id = _id, \ 163991b4e487SEugen Hristev .name = _name_str, \ 164091b4e487SEugen Hristev .type = V4L2_CTRL_TYPE_INTEGER, \ 164191b4e487SEugen Hristev .flags = V4L2_CTRL_FLAG_SLIDER, \ 164291b4e487SEugen Hristev .min = 0, \ 164391b4e487SEugen Hristev .max = 8191, \ 164491b4e487SEugen Hristev .step = 1, \ 164591b4e487SEugen Hristev .def = 512, \ 164691b4e487SEugen Hristev } 164791b4e487SEugen Hristev 164891b4e487SEugen Hristev ISC_CTRL_GAIN(isc_r_gain_ctrl, ISC_CID_R_GAIN, "Red Component Gain"); 164991b4e487SEugen Hristev ISC_CTRL_GAIN(isc_b_gain_ctrl, ISC_CID_B_GAIN, "Blue Component Gain"); 165091b4e487SEugen Hristev ISC_CTRL_GAIN(isc_gr_gain_ctrl, ISC_CID_GR_GAIN, "Green Red Component Gain"); 165191b4e487SEugen Hristev ISC_CTRL_GAIN(isc_gb_gain_ctrl, ISC_CID_GB_GAIN, "Green Blue Component Gain"); 165291b4e487SEugen Hristev 165391b4e487SEugen Hristev static int isc_ctrl_init(struct isc_device *isc) 165491b4e487SEugen Hristev { 165591b4e487SEugen Hristev const struct v4l2_ctrl_ops *ops = &isc_ctrl_ops; 165691b4e487SEugen Hristev struct isc_ctrls *ctrls = &isc->ctrls; 165791b4e487SEugen Hristev struct v4l2_ctrl_handler *hdl = &ctrls->handler; 165891b4e487SEugen Hristev int ret; 165991b4e487SEugen Hristev 166091b4e487SEugen Hristev ctrls->hist_stat = HIST_INIT; 166191b4e487SEugen Hristev isc_reset_awb_ctrls(isc); 166291b4e487SEugen Hristev 166391b4e487SEugen Hristev ret = v4l2_ctrl_handler_init(hdl, 13); 166491b4e487SEugen Hristev if (ret < 0) 166591b4e487SEugen Hristev return ret; 166691b4e487SEugen Hristev 166791b4e487SEugen Hristev /* Initialize product specific controls. For example, contrast */ 166891b4e487SEugen Hristev isc->config_ctrls(isc, ops); 166991b4e487SEugen Hristev 167091b4e487SEugen Hristev ctrls->brightness = 0; 167191b4e487SEugen Hristev 167291b4e487SEugen Hristev v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BRIGHTNESS, -1024, 1023, 1, 0); 167391b4e487SEugen Hristev v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAMMA, 0, isc->gamma_max, 1, 167491b4e487SEugen Hristev isc->gamma_max); 167591b4e487SEugen Hristev isc->awb_ctrl = v4l2_ctrl_new_std(hdl, &isc_awb_ops, 167691b4e487SEugen Hristev V4L2_CID_AUTO_WHITE_BALANCE, 167791b4e487SEugen Hristev 0, 1, 1, 1); 167891b4e487SEugen Hristev 167991b4e487SEugen Hristev /* do_white_balance is a button, so min,max,step,default are ignored */ 168091b4e487SEugen Hristev isc->do_wb_ctrl = v4l2_ctrl_new_std(hdl, &isc_awb_ops, 168191b4e487SEugen Hristev V4L2_CID_DO_WHITE_BALANCE, 168291b4e487SEugen Hristev 0, 0, 0, 0); 168391b4e487SEugen Hristev 168491b4e487SEugen Hristev if (!isc->do_wb_ctrl) { 168591b4e487SEugen Hristev ret = hdl->error; 168691b4e487SEugen Hristev v4l2_ctrl_handler_free(hdl); 168791b4e487SEugen Hristev return ret; 168891b4e487SEugen Hristev } 168991b4e487SEugen Hristev 169091b4e487SEugen Hristev v4l2_ctrl_activate(isc->do_wb_ctrl, false); 169191b4e487SEugen Hristev 169291b4e487SEugen Hristev isc->r_gain_ctrl = v4l2_ctrl_new_custom(hdl, &isc_r_gain_ctrl, NULL); 169391b4e487SEugen Hristev isc->b_gain_ctrl = v4l2_ctrl_new_custom(hdl, &isc_b_gain_ctrl, NULL); 169491b4e487SEugen Hristev isc->gr_gain_ctrl = v4l2_ctrl_new_custom(hdl, &isc_gr_gain_ctrl, NULL); 169591b4e487SEugen Hristev isc->gb_gain_ctrl = v4l2_ctrl_new_custom(hdl, &isc_gb_gain_ctrl, NULL); 169691b4e487SEugen Hristev isc->r_off_ctrl = v4l2_ctrl_new_custom(hdl, &isc_r_off_ctrl, NULL); 169791b4e487SEugen Hristev isc->b_off_ctrl = v4l2_ctrl_new_custom(hdl, &isc_b_off_ctrl, NULL); 169891b4e487SEugen Hristev isc->gr_off_ctrl = v4l2_ctrl_new_custom(hdl, &isc_gr_off_ctrl, NULL); 169991b4e487SEugen Hristev isc->gb_off_ctrl = v4l2_ctrl_new_custom(hdl, &isc_gb_off_ctrl, NULL); 170091b4e487SEugen Hristev 170191b4e487SEugen Hristev /* 170291b4e487SEugen Hristev * The cluster is in auto mode with autowhitebalance enabled 170391b4e487SEugen Hristev * and manual mode otherwise. 170491b4e487SEugen Hristev */ 170591b4e487SEugen Hristev v4l2_ctrl_auto_cluster(10, &isc->awb_ctrl, 0, true); 170691b4e487SEugen Hristev 170791b4e487SEugen Hristev v4l2_ctrl_handler_setup(hdl); 170891b4e487SEugen Hristev 170991b4e487SEugen Hristev return 0; 171091b4e487SEugen Hristev } 171191b4e487SEugen Hristev 171291b4e487SEugen Hristev static int isc_async_bound(struct v4l2_async_notifier *notifier, 171391b4e487SEugen Hristev struct v4l2_subdev *subdev, 171491b4e487SEugen Hristev struct v4l2_async_subdev *asd) 171591b4e487SEugen Hristev { 171691b4e487SEugen Hristev struct isc_device *isc = container_of(notifier->v4l2_dev, 171791b4e487SEugen Hristev struct isc_device, v4l2_dev); 171891b4e487SEugen Hristev struct isc_subdev_entity *subdev_entity = 171991b4e487SEugen Hristev container_of(notifier, struct isc_subdev_entity, notifier); 1720920b2665SEugen Hristev int pad; 172191b4e487SEugen Hristev 172291b4e487SEugen Hristev if (video_is_registered(&isc->video_dev)) { 1723*8d46c5cdSEugen Hristev dev_err(isc->dev, "only supports one sub-device.\n"); 172491b4e487SEugen Hristev return -EBUSY; 172591b4e487SEugen Hristev } 172691b4e487SEugen Hristev 172791b4e487SEugen Hristev subdev_entity->sd = subdev; 172891b4e487SEugen Hristev 1729920b2665SEugen Hristev pad = media_entity_get_fwnode_pad(&subdev->entity, asd->match.fwnode, 1730920b2665SEugen Hristev MEDIA_PAD_FL_SOURCE); 1731920b2665SEugen Hristev if (pad < 0) { 1732*8d46c5cdSEugen Hristev dev_err(isc->dev, "failed to find pad for %s\n", subdev->name); 1733920b2665SEugen Hristev return pad; 1734920b2665SEugen Hristev } 1735920b2665SEugen Hristev 1736920b2665SEugen Hristev isc->remote_pad = pad; 1737920b2665SEugen Hristev 173891b4e487SEugen Hristev return 0; 173991b4e487SEugen Hristev } 174091b4e487SEugen Hristev 174191b4e487SEugen Hristev static void isc_async_unbind(struct v4l2_async_notifier *notifier, 174291b4e487SEugen Hristev struct v4l2_subdev *subdev, 174391b4e487SEugen Hristev struct v4l2_async_subdev *asd) 174491b4e487SEugen Hristev { 174591b4e487SEugen Hristev struct isc_device *isc = container_of(notifier->v4l2_dev, 174691b4e487SEugen Hristev struct isc_device, v4l2_dev); 174791b4e487SEugen Hristev mutex_destroy(&isc->awb_mutex); 174891b4e487SEugen Hristev cancel_work_sync(&isc->awb_work); 174991b4e487SEugen Hristev video_unregister_device(&isc->video_dev); 175091b4e487SEugen Hristev v4l2_ctrl_handler_free(&isc->ctrls.handler); 175191b4e487SEugen Hristev } 175291b4e487SEugen Hristev 1753920b2665SEugen Hristev struct isc_format *isc_find_format_by_code(struct isc_device *isc, 175491b4e487SEugen Hristev unsigned int code, int *index) 175591b4e487SEugen Hristev { 175691b4e487SEugen Hristev struct isc_format *fmt = &isc->formats_list[0]; 175791b4e487SEugen Hristev unsigned int i; 175891b4e487SEugen Hristev 175991b4e487SEugen Hristev for (i = 0; i < isc->formats_list_size; i++) { 176091b4e487SEugen Hristev if (fmt->mbus_code == code) { 176191b4e487SEugen Hristev *index = i; 176291b4e487SEugen Hristev return fmt; 176391b4e487SEugen Hristev } 176491b4e487SEugen Hristev 176591b4e487SEugen Hristev fmt++; 176691b4e487SEugen Hristev } 176791b4e487SEugen Hristev 176891b4e487SEugen Hristev return NULL; 176991b4e487SEugen Hristev } 1770920b2665SEugen Hristev EXPORT_SYMBOL_GPL(isc_find_format_by_code); 177191b4e487SEugen Hristev 177291b4e487SEugen Hristev static int isc_set_default_fmt(struct isc_device *isc) 177391b4e487SEugen Hristev { 177491b4e487SEugen Hristev struct v4l2_format f = { 177591b4e487SEugen Hristev .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, 177691b4e487SEugen Hristev .fmt.pix = { 177791b4e487SEugen Hristev .width = VGA_WIDTH, 177891b4e487SEugen Hristev .height = VGA_HEIGHT, 177991b4e487SEugen Hristev .field = V4L2_FIELD_NONE, 178078ba0d79SEugen Hristev .pixelformat = isc->controller_formats[0].fourcc, 178191b4e487SEugen Hristev }, 178291b4e487SEugen Hristev }; 178391b4e487SEugen Hristev int ret; 178491b4e487SEugen Hristev 178578ba0d79SEugen Hristev ret = isc_try_fmt(isc, &f); 178691b4e487SEugen Hristev if (ret) 178791b4e487SEugen Hristev return ret; 178891b4e487SEugen Hristev 178991b4e487SEugen Hristev isc->fmt = f; 179091b4e487SEugen Hristev return 0; 179191b4e487SEugen Hristev } 179291b4e487SEugen Hristev 179391b4e487SEugen Hristev static int isc_async_complete(struct v4l2_async_notifier *notifier) 179491b4e487SEugen Hristev { 179591b4e487SEugen Hristev struct isc_device *isc = container_of(notifier->v4l2_dev, 179691b4e487SEugen Hristev struct isc_device, v4l2_dev); 179791b4e487SEugen Hristev struct video_device *vdev = &isc->video_dev; 179891b4e487SEugen Hristev struct vb2_queue *q = &isc->vb2_vidq; 179991b4e487SEugen Hristev int ret = 0; 180091b4e487SEugen Hristev 180191b4e487SEugen Hristev INIT_WORK(&isc->awb_work, isc_awb_work); 180291b4e487SEugen Hristev 180391b4e487SEugen Hristev ret = v4l2_device_register_subdev_nodes(&isc->v4l2_dev); 180491b4e487SEugen Hristev if (ret < 0) { 1805*8d46c5cdSEugen Hristev dev_err(isc->dev, "Failed to register subdev nodes\n"); 180691b4e487SEugen Hristev return ret; 180791b4e487SEugen Hristev } 180891b4e487SEugen Hristev 180991b4e487SEugen Hristev isc->current_subdev = container_of(notifier, 181091b4e487SEugen Hristev struct isc_subdev_entity, notifier); 181191b4e487SEugen Hristev mutex_init(&isc->lock); 181291b4e487SEugen Hristev mutex_init(&isc->awb_mutex); 181391b4e487SEugen Hristev 181491b4e487SEugen Hristev init_completion(&isc->comp); 181591b4e487SEugen Hristev 181691b4e487SEugen Hristev /* Initialize videobuf2 queue */ 181791b4e487SEugen Hristev q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 181891b4e487SEugen Hristev q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ; 181991b4e487SEugen Hristev q->drv_priv = isc; 182091b4e487SEugen Hristev q->buf_struct_size = sizeof(struct isc_buffer); 182191b4e487SEugen Hristev q->ops = &isc_vb2_ops; 182291b4e487SEugen Hristev q->mem_ops = &vb2_dma_contig_memops; 182391b4e487SEugen Hristev q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; 182491b4e487SEugen Hristev q->lock = &isc->lock; 182591b4e487SEugen Hristev q->min_buffers_needed = 1; 182691b4e487SEugen Hristev q->dev = isc->dev; 182791b4e487SEugen Hristev 182891b4e487SEugen Hristev ret = vb2_queue_init(q); 182991b4e487SEugen Hristev if (ret < 0) { 1830*8d46c5cdSEugen Hristev dev_err(isc->dev, "vb2_queue_init() failed: %d\n", ret); 183191b4e487SEugen Hristev goto isc_async_complete_err; 183291b4e487SEugen Hristev } 183391b4e487SEugen Hristev 183491b4e487SEugen Hristev /* Init video dma queues */ 183591b4e487SEugen Hristev INIT_LIST_HEAD(&isc->dma_queue); 183691b4e487SEugen Hristev spin_lock_init(&isc->dma_queue_lock); 183791b4e487SEugen Hristev spin_lock_init(&isc->awb_lock); 183891b4e487SEugen Hristev 183991b4e487SEugen Hristev ret = isc_set_default_fmt(isc); 184091b4e487SEugen Hristev if (ret) { 1841*8d46c5cdSEugen Hristev dev_err(isc->dev, "Could not set default format\n"); 184291b4e487SEugen Hristev goto isc_async_complete_err; 184391b4e487SEugen Hristev } 184491b4e487SEugen Hristev 184591b4e487SEugen Hristev ret = isc_ctrl_init(isc); 184691b4e487SEugen Hristev if (ret) { 1847*8d46c5cdSEugen Hristev dev_err(isc->dev, "Init isc ctrols failed: %d\n", ret); 184891b4e487SEugen Hristev goto isc_async_complete_err; 184991b4e487SEugen Hristev } 185091b4e487SEugen Hristev 185191b4e487SEugen Hristev /* Register video device */ 185291b4e487SEugen Hristev strscpy(vdev->name, KBUILD_MODNAME, sizeof(vdev->name)); 185391b4e487SEugen Hristev vdev->release = video_device_release_empty; 185491b4e487SEugen Hristev vdev->fops = &isc_fops; 185591b4e487SEugen Hristev vdev->ioctl_ops = &isc_ioctl_ops; 185691b4e487SEugen Hristev vdev->v4l2_dev = &isc->v4l2_dev; 185791b4e487SEugen Hristev vdev->vfl_dir = VFL_DIR_RX; 185891b4e487SEugen Hristev vdev->queue = q; 185991b4e487SEugen Hristev vdev->lock = &isc->lock; 186091b4e487SEugen Hristev vdev->ctrl_handler = &isc->ctrls.handler; 186178ba0d79SEugen Hristev vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE | 186278ba0d79SEugen Hristev V4L2_CAP_IO_MC; 186391b4e487SEugen Hristev video_set_drvdata(vdev, isc); 186491b4e487SEugen Hristev 186591b4e487SEugen Hristev ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); 186691b4e487SEugen Hristev if (ret < 0) { 1867*8d46c5cdSEugen Hristev dev_err(isc->dev, "video_register_device failed: %d\n", ret); 186891b4e487SEugen Hristev goto isc_async_complete_err; 186991b4e487SEugen Hristev } 187091b4e487SEugen Hristev 1871920b2665SEugen Hristev ret = isc_scaler_link(isc); 1872920b2665SEugen Hristev if (ret < 0) 1873920b2665SEugen Hristev goto isc_async_complete_unregister_device; 1874920b2665SEugen Hristev 1875920b2665SEugen Hristev ret = media_device_register(&isc->mdev); 1876920b2665SEugen Hristev if (ret < 0) 1877920b2665SEugen Hristev goto isc_async_complete_unregister_device; 1878920b2665SEugen Hristev 187991b4e487SEugen Hristev return 0; 188091b4e487SEugen Hristev 1881920b2665SEugen Hristev isc_async_complete_unregister_device: 1882920b2665SEugen Hristev video_unregister_device(vdev); 1883920b2665SEugen Hristev 188491b4e487SEugen Hristev isc_async_complete_err: 188591b4e487SEugen Hristev mutex_destroy(&isc->awb_mutex); 188691b4e487SEugen Hristev mutex_destroy(&isc->lock); 188791b4e487SEugen Hristev return ret; 188891b4e487SEugen Hristev } 188991b4e487SEugen Hristev 189091b4e487SEugen Hristev const struct v4l2_async_notifier_operations microchip_isc_async_ops = { 189191b4e487SEugen Hristev .bound = isc_async_bound, 189291b4e487SEugen Hristev .unbind = isc_async_unbind, 189391b4e487SEugen Hristev .complete = isc_async_complete, 189491b4e487SEugen Hristev }; 189591b4e487SEugen Hristev EXPORT_SYMBOL_GPL(microchip_isc_async_ops); 189691b4e487SEugen Hristev 189791b4e487SEugen Hristev void microchip_isc_subdev_cleanup(struct isc_device *isc) 189891b4e487SEugen Hristev { 189991b4e487SEugen Hristev struct isc_subdev_entity *subdev_entity; 190091b4e487SEugen Hristev 190191b4e487SEugen Hristev list_for_each_entry(subdev_entity, &isc->subdev_entities, list) { 190291b4e487SEugen Hristev v4l2_async_nf_unregister(&subdev_entity->notifier); 190391b4e487SEugen Hristev v4l2_async_nf_cleanup(&subdev_entity->notifier); 190491b4e487SEugen Hristev } 190591b4e487SEugen Hristev 190691b4e487SEugen Hristev INIT_LIST_HEAD(&isc->subdev_entities); 190791b4e487SEugen Hristev } 190891b4e487SEugen Hristev EXPORT_SYMBOL_GPL(microchip_isc_subdev_cleanup); 190991b4e487SEugen Hristev 191091b4e487SEugen Hristev int microchip_isc_pipeline_init(struct isc_device *isc) 191191b4e487SEugen Hristev { 191291b4e487SEugen Hristev struct device *dev = isc->dev; 191391b4e487SEugen Hristev struct regmap *regmap = isc->regmap; 191491b4e487SEugen Hristev struct regmap_field *regs; 191591b4e487SEugen Hristev unsigned int i; 191691b4e487SEugen Hristev 191791b4e487SEugen Hristev /* 191891b4e487SEugen Hristev * DPCEN-->GDCEN-->BLCEN-->WB-->CFA-->CC--> 191991b4e487SEugen Hristev * GAM-->VHXS-->CSC-->CBC-->SUB422-->SUB420 192091b4e487SEugen Hristev */ 192191b4e487SEugen Hristev const struct reg_field regfields[ISC_PIPE_LINE_NODE_NUM] = { 192291b4e487SEugen Hristev REG_FIELD(ISC_DPC_CTRL, 0, 0), 192391b4e487SEugen Hristev REG_FIELD(ISC_DPC_CTRL, 1, 1), 192491b4e487SEugen Hristev REG_FIELD(ISC_DPC_CTRL, 2, 2), 192591b4e487SEugen Hristev REG_FIELD(ISC_WB_CTRL, 0, 0), 192691b4e487SEugen Hristev REG_FIELD(ISC_CFA_CTRL, 0, 0), 192791b4e487SEugen Hristev REG_FIELD(ISC_CC_CTRL, 0, 0), 192891b4e487SEugen Hristev REG_FIELD(ISC_GAM_CTRL, 0, 0), 192991b4e487SEugen Hristev REG_FIELD(ISC_GAM_CTRL, 1, 1), 193091b4e487SEugen Hristev REG_FIELD(ISC_GAM_CTRL, 2, 2), 193191b4e487SEugen Hristev REG_FIELD(ISC_GAM_CTRL, 3, 3), 193291b4e487SEugen Hristev REG_FIELD(ISC_VHXS_CTRL, 0, 0), 193391b4e487SEugen Hristev REG_FIELD(ISC_CSC_CTRL + isc->offsets.csc, 0, 0), 193491b4e487SEugen Hristev REG_FIELD(ISC_CBC_CTRL + isc->offsets.cbc, 0, 0), 193591b4e487SEugen Hristev REG_FIELD(ISC_SUB422_CTRL + isc->offsets.sub422, 0, 0), 193691b4e487SEugen Hristev REG_FIELD(ISC_SUB420_CTRL + isc->offsets.sub420, 0, 0), 193791b4e487SEugen Hristev }; 193891b4e487SEugen Hristev 193991b4e487SEugen Hristev for (i = 0; i < ISC_PIPE_LINE_NODE_NUM; i++) { 194091b4e487SEugen Hristev regs = devm_regmap_field_alloc(dev, regmap, regfields[i]); 194191b4e487SEugen Hristev if (IS_ERR(regs)) 194291b4e487SEugen Hristev return PTR_ERR(regs); 194391b4e487SEugen Hristev 194491b4e487SEugen Hristev isc->pipeline[i] = regs; 194591b4e487SEugen Hristev } 194691b4e487SEugen Hristev 194791b4e487SEugen Hristev return 0; 194891b4e487SEugen Hristev } 194991b4e487SEugen Hristev EXPORT_SYMBOL_GPL(microchip_isc_pipeline_init); 195091b4e487SEugen Hristev 195178ba0d79SEugen Hristev static int isc_link_validate(struct media_link *link) 195278ba0d79SEugen Hristev { 195378ba0d79SEugen Hristev struct video_device *vdev = 195478ba0d79SEugen Hristev media_entity_to_video_device(link->sink->entity); 195578ba0d79SEugen Hristev struct isc_device *isc = video_get_drvdata(vdev); 195678ba0d79SEugen Hristev int ret; 195778ba0d79SEugen Hristev 195878ba0d79SEugen Hristev ret = v4l2_subdev_link_validate(link); 195978ba0d79SEugen Hristev if (ret) 196078ba0d79SEugen Hristev return ret; 196178ba0d79SEugen Hristev 196278ba0d79SEugen Hristev return isc_validate(isc); 196378ba0d79SEugen Hristev } 196478ba0d79SEugen Hristev 196578ba0d79SEugen Hristev static const struct media_entity_operations isc_entity_operations = { 196678ba0d79SEugen Hristev .link_validate = isc_link_validate, 196778ba0d79SEugen Hristev }; 196878ba0d79SEugen Hristev 1969920b2665SEugen Hristev int isc_mc_init(struct isc_device *isc, u32 ver) 1970920b2665SEugen Hristev { 1971920b2665SEugen Hristev const struct of_device_id *match; 1972920b2665SEugen Hristev int ret; 1973920b2665SEugen Hristev 1974920b2665SEugen Hristev isc->video_dev.entity.function = MEDIA_ENT_F_IO_V4L; 1975920b2665SEugen Hristev isc->video_dev.entity.flags = MEDIA_ENT_FL_DEFAULT; 197678ba0d79SEugen Hristev isc->video_dev.entity.ops = &isc_entity_operations; 197778ba0d79SEugen Hristev 1978920b2665SEugen Hristev isc->pads[ISC_PAD_SINK].flags = MEDIA_PAD_FL_SINK; 1979920b2665SEugen Hristev 1980920b2665SEugen Hristev ret = media_entity_pads_init(&isc->video_dev.entity, ISC_PADS_NUM, 1981920b2665SEugen Hristev isc->pads); 1982920b2665SEugen Hristev if (ret < 0) { 1983920b2665SEugen Hristev dev_err(isc->dev, "media entity init failed\n"); 1984920b2665SEugen Hristev return ret; 1985920b2665SEugen Hristev } 1986920b2665SEugen Hristev 1987920b2665SEugen Hristev isc->mdev.dev = isc->dev; 1988920b2665SEugen Hristev 1989920b2665SEugen Hristev match = of_match_node(isc->dev->driver->of_match_table, 1990920b2665SEugen Hristev isc->dev->of_node); 1991920b2665SEugen Hristev 1992920b2665SEugen Hristev strscpy(isc->mdev.driver_name, KBUILD_MODNAME, 1993920b2665SEugen Hristev sizeof(isc->mdev.driver_name)); 1994920b2665SEugen Hristev strscpy(isc->mdev.model, match->compatible, sizeof(isc->mdev.model)); 1995920b2665SEugen Hristev snprintf(isc->mdev.bus_info, sizeof(isc->mdev.bus_info), "platform:%s", 1996920b2665SEugen Hristev isc->v4l2_dev.name); 1997920b2665SEugen Hristev isc->mdev.hw_revision = ver; 1998920b2665SEugen Hristev 1999920b2665SEugen Hristev media_device_init(&isc->mdev); 2000920b2665SEugen Hristev 2001920b2665SEugen Hristev isc->v4l2_dev.mdev = &isc->mdev; 2002920b2665SEugen Hristev 2003920b2665SEugen Hristev return isc_scaler_init(isc); 2004920b2665SEugen Hristev } 2005920b2665SEugen Hristev EXPORT_SYMBOL_GPL(isc_mc_init); 2006920b2665SEugen Hristev 2007920b2665SEugen Hristev void isc_mc_cleanup(struct isc_device *isc) 2008920b2665SEugen Hristev { 2009920b2665SEugen Hristev media_entity_cleanup(&isc->video_dev.entity); 2010920b2665SEugen Hristev media_device_cleanup(&isc->mdev); 2011920b2665SEugen Hristev } 2012920b2665SEugen Hristev EXPORT_SYMBOL_GPL(isc_mc_cleanup); 2013920b2665SEugen Hristev 201491b4e487SEugen Hristev /* regmap configuration */ 201591b4e487SEugen Hristev #define MICROCHIP_ISC_REG_MAX 0xd5c 201691b4e487SEugen Hristev const struct regmap_config microchip_isc_regmap_config = { 201791b4e487SEugen Hristev .reg_bits = 32, 201891b4e487SEugen Hristev .reg_stride = 4, 201991b4e487SEugen Hristev .val_bits = 32, 202091b4e487SEugen Hristev .max_register = MICROCHIP_ISC_REG_MAX, 202191b4e487SEugen Hristev }; 202291b4e487SEugen Hristev EXPORT_SYMBOL_GPL(microchip_isc_regmap_config); 202391b4e487SEugen Hristev 202491b4e487SEugen Hristev MODULE_AUTHOR("Songjun Wu"); 202591b4e487SEugen Hristev MODULE_AUTHOR("Eugen Hristev"); 202691b4e487SEugen Hristev MODULE_DESCRIPTION("Microchip ISC common code base"); 202791b4e487SEugen Hristev MODULE_LICENSE("GPL v2"); 2028