162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Pixart PAC207BCA / PAC73xx common functions
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2008 Hans de Goede <j.w.r.degoede@hhs.nl>
662306a36Sopenharmony_ci * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
762306a36Sopenharmony_ci * Copyleft (C) 2005 Michel Xhaard mxhaard@magic.fr
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci/* We calculate the autogain at the end of the transfer of a frame, at this
1362306a36Sopenharmony_ci   moment a frame with the old settings is being captured and transmitted. So
1462306a36Sopenharmony_ci   if we adjust the gain or exposure we must ignore at least the next frame for
1562306a36Sopenharmony_ci   the new settings to come into effect before doing any other adjustments. */
1662306a36Sopenharmony_ci#define PAC_AUTOGAIN_IGNORE_FRAMES	2
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_cistatic const unsigned char pac_sof_marker[5] =
1962306a36Sopenharmony_ci		{ 0xff, 0xff, 0x00, 0xff, 0x96 };
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci/*
2262306a36Sopenharmony_ci   The following state machine finds the SOF marker sequence
2362306a36Sopenharmony_ci   0xff, 0xff, 0x00, 0xff, 0x96 in a byte stream.
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci	   +----------+
2662306a36Sopenharmony_ci	   | 0: START |<---------------\
2762306a36Sopenharmony_ci	   +----------+<-\             |
2862306a36Sopenharmony_ci	     |       \---/otherwise    |
2962306a36Sopenharmony_ci	     v 0xff                    |
3062306a36Sopenharmony_ci	   +----------+ otherwise      |
3162306a36Sopenharmony_ci	   |     1    |--------------->*
3262306a36Sopenharmony_ci	   |          |                ^
3362306a36Sopenharmony_ci	   +----------+                |
3462306a36Sopenharmony_ci	     |                         |
3562306a36Sopenharmony_ci	     v 0xff                    |
3662306a36Sopenharmony_ci	   +----------+<-\0xff         |
3762306a36Sopenharmony_ci	/->|          |--/             |
3862306a36Sopenharmony_ci	|  |     2    |--------------->*
3962306a36Sopenharmony_ci	|  |          | otherwise      ^
4062306a36Sopenharmony_ci	|  +----------+                |
4162306a36Sopenharmony_ci	|    |                         |
4262306a36Sopenharmony_ci	|    v 0x00                    |
4362306a36Sopenharmony_ci	|  +----------+                |
4462306a36Sopenharmony_ci	|  |     3    |                |
4562306a36Sopenharmony_ci	|  |          |--------------->*
4662306a36Sopenharmony_ci	|  +----------+ otherwise      ^
4762306a36Sopenharmony_ci	|    |                         |
4862306a36Sopenharmony_ci   0xff |    v 0xff                    |
4962306a36Sopenharmony_ci	|  +----------+                |
5062306a36Sopenharmony_ci	\--|     4    |                |
5162306a36Sopenharmony_ci	   |          |----------------/
5262306a36Sopenharmony_ci	   +----------+ otherwise
5362306a36Sopenharmony_ci	     |
5462306a36Sopenharmony_ci	     v 0x96
5562306a36Sopenharmony_ci	   +----------+
5662306a36Sopenharmony_ci	   |  FOUND   |
5762306a36Sopenharmony_ci	   +----------+
5862306a36Sopenharmony_ci*/
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_cistatic unsigned char *pac_find_sof(struct gspca_dev *gspca_dev, u8 *sof_read,
6162306a36Sopenharmony_ci					unsigned char *m, int len)
6262306a36Sopenharmony_ci{
6362306a36Sopenharmony_ci	int i;
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	/* Search for the SOF marker (fixed part) in the header */
6662306a36Sopenharmony_ci	for (i = 0; i < len; i++) {
6762306a36Sopenharmony_ci		switch (*sof_read) {
6862306a36Sopenharmony_ci		case 0:
6962306a36Sopenharmony_ci			if (m[i] == 0xff)
7062306a36Sopenharmony_ci				*sof_read = 1;
7162306a36Sopenharmony_ci			break;
7262306a36Sopenharmony_ci		case 1:
7362306a36Sopenharmony_ci			if (m[i] == 0xff)
7462306a36Sopenharmony_ci				*sof_read = 2;
7562306a36Sopenharmony_ci			else
7662306a36Sopenharmony_ci				*sof_read = 0;
7762306a36Sopenharmony_ci			break;
7862306a36Sopenharmony_ci		case 2:
7962306a36Sopenharmony_ci			switch (m[i]) {
8062306a36Sopenharmony_ci			case 0x00:
8162306a36Sopenharmony_ci				*sof_read = 3;
8262306a36Sopenharmony_ci				break;
8362306a36Sopenharmony_ci			case 0xff:
8462306a36Sopenharmony_ci				/* stay in this state */
8562306a36Sopenharmony_ci				break;
8662306a36Sopenharmony_ci			default:
8762306a36Sopenharmony_ci				*sof_read = 0;
8862306a36Sopenharmony_ci			}
8962306a36Sopenharmony_ci			break;
9062306a36Sopenharmony_ci		case 3:
9162306a36Sopenharmony_ci			if (m[i] == 0xff)
9262306a36Sopenharmony_ci				*sof_read = 4;
9362306a36Sopenharmony_ci			else
9462306a36Sopenharmony_ci				*sof_read = 0;
9562306a36Sopenharmony_ci			break;
9662306a36Sopenharmony_ci		case 4:
9762306a36Sopenharmony_ci			switch (m[i]) {
9862306a36Sopenharmony_ci			case 0x96:
9962306a36Sopenharmony_ci				/* Pattern found */
10062306a36Sopenharmony_ci				gspca_dbg(gspca_dev, D_FRAM,
10162306a36Sopenharmony_ci					  "SOF found, bytes to analyze: %u - Frame starts at byte #%u\n",
10262306a36Sopenharmony_ci					  len, i + 1);
10362306a36Sopenharmony_ci				*sof_read = 0;
10462306a36Sopenharmony_ci				return m + i + 1;
10562306a36Sopenharmony_ci				break;
10662306a36Sopenharmony_ci			case 0xff:
10762306a36Sopenharmony_ci				*sof_read = 2;
10862306a36Sopenharmony_ci				break;
10962306a36Sopenharmony_ci			default:
11062306a36Sopenharmony_ci				*sof_read = 0;
11162306a36Sopenharmony_ci			}
11262306a36Sopenharmony_ci			break;
11362306a36Sopenharmony_ci		default:
11462306a36Sopenharmony_ci			*sof_read = 0;
11562306a36Sopenharmony_ci		}
11662306a36Sopenharmony_ci	}
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	return NULL;
11962306a36Sopenharmony_ci}
120