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