cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

isph3a_af.c (11112B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * isph3a_af.c
      4 *
      5 * TI OMAP3 ISP - H3A AF module
      6 *
      7 * Copyright (C) 2010 Nokia Corporation
      8 * Copyright (C) 2009 Texas Instruments, Inc.
      9 *
     10 * Contacts: David Cohen <dacohen@gmail.com>
     11 *	     Laurent Pinchart <laurent.pinchart@ideasonboard.com>
     12 *	     Sakari Ailus <sakari.ailus@iki.fi>
     13 */
     14
     15/* Linux specific include files */
     16#include <linux/device.h>
     17#include <linux/slab.h>
     18
     19#include "isp.h"
     20#include "isph3a.h"
     21#include "ispstat.h"
     22
     23#define IS_OUT_OF_BOUNDS(value, min, max)		\
     24	((((unsigned int)value) < (min)) || (((unsigned int)value) > (max)))
     25
     26static void h3a_af_setup_regs(struct ispstat *af, void *priv)
     27{
     28	struct omap3isp_h3a_af_config *conf = priv;
     29	u32 pcr;
     30	u32 pax1;
     31	u32 pax2;
     32	u32 paxstart;
     33	u32 coef;
     34	u32 base_coef_set0;
     35	u32 base_coef_set1;
     36	int index;
     37
     38	if (af->state == ISPSTAT_DISABLED)
     39		return;
     40
     41	isp_reg_writel(af->isp, af->active_buf->dma_addr, OMAP3_ISP_IOMEM_H3A,
     42		       ISPH3A_AFBUFST);
     43
     44	if (!af->update)
     45		return;
     46
     47	/* Configure Hardware Registers */
     48	pax1 = ((conf->paxel.width >> 1) - 1) << AF_PAXW_SHIFT;
     49	/* Set height in AFPAX1 */
     50	pax1 |= (conf->paxel.height >> 1) - 1;
     51	isp_reg_writel(af->isp, pax1, OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAX1);
     52
     53	/* Configure AFPAX2 Register */
     54	/* Set Line Increment in AFPAX2 Register */
     55	pax2 = ((conf->paxel.line_inc >> 1) - 1) << AF_LINE_INCR_SHIFT;
     56	/* Set Vertical Count */
     57	pax2 |= (conf->paxel.v_cnt - 1) << AF_VT_COUNT_SHIFT;
     58	/* Set Horizontal Count */
     59	pax2 |= (conf->paxel.h_cnt - 1);
     60	isp_reg_writel(af->isp, pax2, OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAX2);
     61
     62	/* Configure PAXSTART Register */
     63	/*Configure Horizontal Start */
     64	paxstart = conf->paxel.h_start << AF_HZ_START_SHIFT;
     65	/* Configure Vertical Start */
     66	paxstart |= conf->paxel.v_start;
     67	isp_reg_writel(af->isp, paxstart, OMAP3_ISP_IOMEM_H3A,
     68		       ISPH3A_AFPAXSTART);
     69
     70	/*SetIIRSH Register */
     71	isp_reg_writel(af->isp, conf->iir.h_start,
     72		       OMAP3_ISP_IOMEM_H3A, ISPH3A_AFIIRSH);
     73
     74	base_coef_set0 = ISPH3A_AFCOEF010;
     75	base_coef_set1 = ISPH3A_AFCOEF110;
     76	for (index = 0; index <= 8; index += 2) {
     77		/*Set IIR Filter0 Coefficients */
     78		coef = 0;
     79		coef |= conf->iir.coeff_set0[index];
     80		coef |= conf->iir.coeff_set0[index + 1] <<
     81			AF_COEF_SHIFT;
     82		isp_reg_writel(af->isp, coef, OMAP3_ISP_IOMEM_H3A,
     83			       base_coef_set0);
     84		base_coef_set0 += AFCOEF_OFFSET;
     85
     86		/*Set IIR Filter1 Coefficients */
     87		coef = 0;
     88		coef |= conf->iir.coeff_set1[index];
     89		coef |= conf->iir.coeff_set1[index + 1] <<
     90			AF_COEF_SHIFT;
     91		isp_reg_writel(af->isp, coef, OMAP3_ISP_IOMEM_H3A,
     92			       base_coef_set1);
     93		base_coef_set1 += AFCOEF_OFFSET;
     94	}
     95	/* set AFCOEF0010 Register */
     96	isp_reg_writel(af->isp, conf->iir.coeff_set0[10],
     97		       OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF0010);
     98	/* set AFCOEF1010 Register */
     99	isp_reg_writel(af->isp, conf->iir.coeff_set1[10],
    100		       OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF1010);
    101
    102	/* PCR Register */
    103	/* Set RGB Position */
    104	pcr = conf->rgb_pos << AF_RGBPOS_SHIFT;
    105	/* Set Accumulator Mode */
    106	if (conf->fvmode == OMAP3ISP_AF_MODE_PEAK)
    107		pcr |= AF_FVMODE;
    108	/* Set A-law */
    109	if (conf->alaw_enable)
    110		pcr |= AF_ALAW_EN;
    111	/* HMF Configurations */
    112	if (conf->hmf.enable) {
    113		/* Enable HMF */
    114		pcr |= AF_MED_EN;
    115		/* Set Median Threshold */
    116		pcr |= conf->hmf.threshold << AF_MED_TH_SHIFT;
    117	}
    118	/* Set PCR Register */
    119	isp_reg_clr_set(af->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
    120			AF_PCR_MASK, pcr);
    121
    122	af->update = 0;
    123	af->config_counter += af->inc_config;
    124	af->inc_config = 0;
    125	af->buf_size = conf->buf_size;
    126}
    127
    128static void h3a_af_enable(struct ispstat *af, int enable)
    129{
    130	if (enable) {
    131		isp_reg_set(af->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
    132			    ISPH3A_PCR_AF_EN);
    133		omap3isp_subclk_enable(af->isp, OMAP3_ISP_SUBCLK_AF);
    134	} else {
    135		isp_reg_clr(af->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
    136			    ISPH3A_PCR_AF_EN);
    137		omap3isp_subclk_disable(af->isp, OMAP3_ISP_SUBCLK_AF);
    138	}
    139}
    140
    141static int h3a_af_busy(struct ispstat *af)
    142{
    143	return isp_reg_readl(af->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR)
    144						& ISPH3A_PCR_BUSYAF;
    145}
    146
    147static u32 h3a_af_get_buf_size(struct omap3isp_h3a_af_config *conf)
    148{
    149	return conf->paxel.h_cnt * conf->paxel.v_cnt * OMAP3ISP_AF_PAXEL_SIZE;
    150}
    151
    152/* Function to check paxel parameters */
    153static int h3a_af_validate_params(struct ispstat *af, void *new_conf)
    154{
    155	struct omap3isp_h3a_af_config *user_cfg = new_conf;
    156	struct omap3isp_h3a_af_paxel *paxel_cfg = &user_cfg->paxel;
    157	struct omap3isp_h3a_af_iir *iir_cfg = &user_cfg->iir;
    158	int index;
    159	u32 buf_size;
    160
    161	/* Check horizontal Count */
    162	if (IS_OUT_OF_BOUNDS(paxel_cfg->h_cnt,
    163			     OMAP3ISP_AF_PAXEL_HORIZONTAL_COUNT_MIN,
    164			     OMAP3ISP_AF_PAXEL_HORIZONTAL_COUNT_MAX))
    165		return -EINVAL;
    166
    167	/* Check Vertical Count */
    168	if (IS_OUT_OF_BOUNDS(paxel_cfg->v_cnt,
    169			     OMAP3ISP_AF_PAXEL_VERTICAL_COUNT_MIN,
    170			     OMAP3ISP_AF_PAXEL_VERTICAL_COUNT_MAX))
    171		return -EINVAL;
    172
    173	if (IS_OUT_OF_BOUNDS(paxel_cfg->height, OMAP3ISP_AF_PAXEL_HEIGHT_MIN,
    174			     OMAP3ISP_AF_PAXEL_HEIGHT_MAX) ||
    175	    paxel_cfg->height % 2)
    176		return -EINVAL;
    177
    178	/* Check width */
    179	if (IS_OUT_OF_BOUNDS(paxel_cfg->width, OMAP3ISP_AF_PAXEL_WIDTH_MIN,
    180			     OMAP3ISP_AF_PAXEL_WIDTH_MAX) ||
    181	    paxel_cfg->width % 2)
    182		return -EINVAL;
    183
    184	/* Check Line Increment */
    185	if (IS_OUT_OF_BOUNDS(paxel_cfg->line_inc,
    186			     OMAP3ISP_AF_PAXEL_INCREMENT_MIN,
    187			     OMAP3ISP_AF_PAXEL_INCREMENT_MAX) ||
    188	    paxel_cfg->line_inc % 2)
    189		return -EINVAL;
    190
    191	/* Check Horizontal Start */
    192	if ((paxel_cfg->h_start < iir_cfg->h_start) ||
    193	    IS_OUT_OF_BOUNDS(paxel_cfg->h_start,
    194			     OMAP3ISP_AF_PAXEL_HZSTART_MIN,
    195			     OMAP3ISP_AF_PAXEL_HZSTART_MAX))
    196		return -EINVAL;
    197
    198	/* Check IIR */
    199	for (index = 0; index < OMAP3ISP_AF_NUM_COEF; index++) {
    200		if ((iir_cfg->coeff_set0[index]) > OMAP3ISP_AF_COEF_MAX)
    201			return -EINVAL;
    202
    203		if ((iir_cfg->coeff_set1[index]) > OMAP3ISP_AF_COEF_MAX)
    204			return -EINVAL;
    205	}
    206
    207	if (IS_OUT_OF_BOUNDS(iir_cfg->h_start, OMAP3ISP_AF_IIRSH_MIN,
    208			     OMAP3ISP_AF_IIRSH_MAX))
    209		return -EINVAL;
    210
    211	/* Hack: If paxel size is 12, the 10th AF window may be corrupted */
    212	if ((paxel_cfg->h_cnt * paxel_cfg->v_cnt > 9) &&
    213	    (paxel_cfg->width * paxel_cfg->height == 12))
    214		return -EINVAL;
    215
    216	buf_size = h3a_af_get_buf_size(user_cfg);
    217	if (buf_size > user_cfg->buf_size)
    218		/* User buf_size request wasn't enough */
    219		user_cfg->buf_size = buf_size;
    220	else if (user_cfg->buf_size > OMAP3ISP_AF_MAX_BUF_SIZE)
    221		user_cfg->buf_size = OMAP3ISP_AF_MAX_BUF_SIZE;
    222
    223	return 0;
    224}
    225
    226/* Update local parameters */
    227static void h3a_af_set_params(struct ispstat *af, void *new_conf)
    228{
    229	struct omap3isp_h3a_af_config *user_cfg = new_conf;
    230	struct omap3isp_h3a_af_config *cur_cfg = af->priv;
    231	int update = 0;
    232	int index;
    233
    234	/* alaw */
    235	if (cur_cfg->alaw_enable != user_cfg->alaw_enable) {
    236		update = 1;
    237		goto out;
    238	}
    239
    240	/* hmf */
    241	if (cur_cfg->hmf.enable != user_cfg->hmf.enable) {
    242		update = 1;
    243		goto out;
    244	}
    245	if (cur_cfg->hmf.threshold != user_cfg->hmf.threshold) {
    246		update = 1;
    247		goto out;
    248	}
    249
    250	/* rgbpos */
    251	if (cur_cfg->rgb_pos != user_cfg->rgb_pos) {
    252		update = 1;
    253		goto out;
    254	}
    255
    256	/* iir */
    257	if (cur_cfg->iir.h_start != user_cfg->iir.h_start) {
    258		update = 1;
    259		goto out;
    260	}
    261	for (index = 0; index < OMAP3ISP_AF_NUM_COEF; index++) {
    262		if (cur_cfg->iir.coeff_set0[index] !=
    263				user_cfg->iir.coeff_set0[index]) {
    264			update = 1;
    265			goto out;
    266		}
    267		if (cur_cfg->iir.coeff_set1[index] !=
    268				user_cfg->iir.coeff_set1[index]) {
    269			update = 1;
    270			goto out;
    271		}
    272	}
    273
    274	/* paxel */
    275	if ((cur_cfg->paxel.width != user_cfg->paxel.width) ||
    276	    (cur_cfg->paxel.height != user_cfg->paxel.height) ||
    277	    (cur_cfg->paxel.h_start != user_cfg->paxel.h_start) ||
    278	    (cur_cfg->paxel.v_start != user_cfg->paxel.v_start) ||
    279	    (cur_cfg->paxel.h_cnt != user_cfg->paxel.h_cnt) ||
    280	    (cur_cfg->paxel.v_cnt != user_cfg->paxel.v_cnt) ||
    281	    (cur_cfg->paxel.line_inc != user_cfg->paxel.line_inc)) {
    282		update = 1;
    283		goto out;
    284	}
    285
    286	/* af_mode */
    287	if (cur_cfg->fvmode != user_cfg->fvmode)
    288		update = 1;
    289
    290out:
    291	if (update || !af->configured) {
    292		memcpy(cur_cfg, user_cfg, sizeof(*cur_cfg));
    293		af->inc_config++;
    294		af->update = 1;
    295		/*
    296		 * User might be asked for a bigger buffer than necessary for
    297		 * this configuration. In order to return the right amount of
    298		 * data during buffer request, let's calculate the size here
    299		 * instead of stick with user_cfg->buf_size.
    300		 */
    301		cur_cfg->buf_size = h3a_af_get_buf_size(cur_cfg);
    302	}
    303}
    304
    305static long h3a_af_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
    306{
    307	struct ispstat *stat = v4l2_get_subdevdata(sd);
    308
    309	switch (cmd) {
    310	case VIDIOC_OMAP3ISP_AF_CFG:
    311		return omap3isp_stat_config(stat, arg);
    312	case VIDIOC_OMAP3ISP_STAT_REQ:
    313		return omap3isp_stat_request_statistics(stat, arg);
    314	case VIDIOC_OMAP3ISP_STAT_REQ_TIME32:
    315		return omap3isp_stat_request_statistics_time32(stat, arg);
    316	case VIDIOC_OMAP3ISP_STAT_EN: {
    317		int *en = arg;
    318		return omap3isp_stat_enable(stat, !!*en);
    319	}
    320	}
    321
    322	return -ENOIOCTLCMD;
    323
    324}
    325
    326static const struct ispstat_ops h3a_af_ops = {
    327	.validate_params	= h3a_af_validate_params,
    328	.set_params		= h3a_af_set_params,
    329	.setup_regs		= h3a_af_setup_regs,
    330	.enable			= h3a_af_enable,
    331	.busy			= h3a_af_busy,
    332};
    333
    334static const struct v4l2_subdev_core_ops h3a_af_subdev_core_ops = {
    335	.ioctl = h3a_af_ioctl,
    336	.subscribe_event = omap3isp_stat_subscribe_event,
    337	.unsubscribe_event = omap3isp_stat_unsubscribe_event,
    338};
    339
    340static const struct v4l2_subdev_video_ops h3a_af_subdev_video_ops = {
    341	.s_stream = omap3isp_stat_s_stream,
    342};
    343
    344static const struct v4l2_subdev_ops h3a_af_subdev_ops = {
    345	.core = &h3a_af_subdev_core_ops,
    346	.video = &h3a_af_subdev_video_ops,
    347};
    348
    349/* Function to register the AF character device driver. */
    350int omap3isp_h3a_af_init(struct isp_device *isp)
    351{
    352	struct ispstat *af = &isp->isp_af;
    353	struct omap3isp_h3a_af_config *af_cfg;
    354	struct omap3isp_h3a_af_config *af_recover_cfg = NULL;
    355	int ret;
    356
    357	af_cfg = kzalloc(sizeof(*af_cfg), GFP_KERNEL);
    358	if (af_cfg == NULL)
    359		return -ENOMEM;
    360
    361	af->ops = &h3a_af_ops;
    362	af->priv = af_cfg;
    363	af->event_type = V4L2_EVENT_OMAP3ISP_AF;
    364	af->isp = isp;
    365
    366	/* Set recover state configuration */
    367	af_recover_cfg = kzalloc(sizeof(*af_recover_cfg), GFP_KERNEL);
    368	if (!af_recover_cfg) {
    369		dev_err(af->isp->dev,
    370			"AF: cannot allocate memory for recover configuration.\n");
    371		ret = -ENOMEM;
    372		goto err;
    373	}
    374
    375	af_recover_cfg->paxel.h_start = OMAP3ISP_AF_PAXEL_HZSTART_MIN;
    376	af_recover_cfg->paxel.width = OMAP3ISP_AF_PAXEL_WIDTH_MIN;
    377	af_recover_cfg->paxel.height = OMAP3ISP_AF_PAXEL_HEIGHT_MIN;
    378	af_recover_cfg->paxel.h_cnt = OMAP3ISP_AF_PAXEL_HORIZONTAL_COUNT_MIN;
    379	af_recover_cfg->paxel.v_cnt = OMAP3ISP_AF_PAXEL_VERTICAL_COUNT_MIN;
    380	af_recover_cfg->paxel.line_inc = OMAP3ISP_AF_PAXEL_INCREMENT_MIN;
    381	if (h3a_af_validate_params(af, af_recover_cfg)) {
    382		dev_err(af->isp->dev,
    383			"AF: recover configuration is invalid.\n");
    384		ret = -EINVAL;
    385		goto err;
    386	}
    387
    388	af_recover_cfg->buf_size = h3a_af_get_buf_size(af_recover_cfg);
    389	af->recover_priv = af_recover_cfg;
    390
    391	ret = omap3isp_stat_init(af, "AF", &h3a_af_subdev_ops);
    392
    393err:
    394	if (ret) {
    395		kfree(af_cfg);
    396		kfree(af_recover_cfg);
    397	}
    398
    399	return ret;
    400}
    401
    402void omap3isp_h3a_af_cleanup(struct isp_device *isp)
    403{
    404	omap3isp_stat_cleanup(&isp->isp_af);
    405}