1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Zoran ZR36060 basic configuration functions
4 *
5 * Copyright (C) 2002 Laurent Pinchart <laurent.pinchart@skynet.be>
6 */
7
8#include <linux/module.h>
9#include <linux/init.h>
10#include <linux/slab.h>
11#include <linux/delay.h>
12
13#include <linux/types.h>
14#include <linux/wait.h>
15
16/* I/O commands, error codes */
17#include <linux/io.h>
18
19/* headerfile of this module */
20#include "zr36060.h"
21
22/* codec io API */
23#include "videocodec.h"
24
25/* it doesn't make sense to have more than 20 or so, just to prevent some unwanted loops */
26#define MAX_CODECS 20
27
28/* amount of chips attached via this driver */
29static int zr36060_codecs;
30
31static bool low_bitrate;
32module_param(low_bitrate, bool, 0);
33MODULE_PARM_DESC(low_bitrate, "Buz compatibility option, halves bitrate");
34
35/* =========================================================================
36 * Local hardware I/O functions:
37 * read/write via codec layer (registers are located in the master device)
38 * =========================================================================
39 */
40
41static u8 zr36060_read(struct zr36060 *ptr, u16 reg)
42{
43	u8 value = 0;
44	struct zoran *zr = videocodec_to_zoran(ptr->codec);
45
46	// just in case something is wrong...
47	if (ptr->codec->master_data->readreg)
48		value = (ptr->codec->master_data->readreg(ptr->codec, reg)) & 0xff;
49	else
50		zrdev_err(zr, "%s: invalid I/O setup, nothing read!\n", ptr->name);
51
52	return value;
53}
54
55static void zr36060_write(struct zr36060 *ptr, u16 reg, u8 value)
56{
57	struct zoran *zr = videocodec_to_zoran(ptr->codec);
58
59	zrdev_dbg(zr, "0x%02x @0x%04x\n", value, reg);
60
61	// just in case something is wrong...
62	if (ptr->codec->master_data->writereg)
63		ptr->codec->master_data->writereg(ptr->codec, reg, value);
64	else
65		zrdev_err(zr, "%s: invalid I/O setup, nothing written!\n", ptr->name);
66}
67
68/* =========================================================================
69 * Local helper function:
70 * status read
71 * =========================================================================
72 */
73
74/* status is kept in datastructure */
75static u8 zr36060_read_status(struct zr36060 *ptr)
76{
77	ptr->status = zr36060_read(ptr, ZR060_CFSR);
78
79	zr36060_read(ptr, 0);
80	return ptr->status;
81}
82
83/* scale factor is kept in datastructure */
84static u16 zr36060_read_scalefactor(struct zr36060 *ptr)
85{
86	ptr->scalefact = (zr36060_read(ptr, ZR060_SF_HI) << 8) |
87			 (zr36060_read(ptr, ZR060_SF_LO) & 0xFF);
88
89	/* leave 0 selected for an eventually GO from master */
90	zr36060_read(ptr, 0);
91	return ptr->scalefact;
92}
93
94/* wait if codec is ready to proceed (end of processing) or time is over */
95static void zr36060_wait_end(struct zr36060 *ptr)
96{
97	struct zoran *zr = videocodec_to_zoran(ptr->codec);
98	int i = 0;
99
100	while (zr36060_read_status(ptr) & ZR060_CFSR_BUSY) {
101		udelay(1);
102		if (i++ > 200000) {	// 200ms, there is for sure something wrong!!!
103			zrdev_dbg(zr,
104				  "%s: timeout at wait_end (last status: 0x%02x)\n",
105				  ptr->name, ptr->status);
106			break;
107		}
108	}
109}
110
111/* Basic test of "connectivity", writes/reads to/from memory the SOF marker */
112static int zr36060_basic_test(struct zr36060 *ptr)
113{
114	struct zoran *zr = videocodec_to_zoran(ptr->codec);
115
116	if ((zr36060_read(ptr, ZR060_IDR_DEV) != 0x33) &&
117	    (zr36060_read(ptr, ZR060_IDR_REV) != 0x01)) {
118		zrdev_err(zr, "%s: attach failed, can't connect to jpeg processor!\n", ptr->name);
119		return -ENXIO;
120	}
121
122	zr36060_wait_end(ptr);
123	if (ptr->status & ZR060_CFSR_BUSY) {
124		zrdev_err(zr, "%s: attach failed, jpeg processor failed (end flag)!\n", ptr->name);
125		return -EBUSY;
126	}
127
128	return 0;		/* looks good! */
129}
130
131/* simple loop for pushing the init datasets */
132static int zr36060_pushit(struct zr36060 *ptr, u16 startreg, u16 len, const char *data)
133{
134	struct zoran *zr = videocodec_to_zoran(ptr->codec);
135	int i = 0;
136
137	zrdev_dbg(zr, "%s: write data block to 0x%04x (len=%d)\n", ptr->name,
138		  startreg, len);
139	while (i < len)
140		zr36060_write(ptr, startreg++, data[i++]);
141
142	return i;
143}
144
145/* =========================================================================
146 * Basic datasets:
147 * jpeg baseline setup data (you find it on lots places in internet, or just
148 * extract it from any regular .jpg image...)
149 *
150 * Could be variable, but until it's not needed it they are just fixed to save
151 * memory. Otherwise expand zr36060 structure with arrays, push the values to
152 * it and initialize from there, as e.g. the linux zr36057/60 driver does it.
153 * =========================================================================
154 */
155static const char zr36060_dqt[0x86] = {
156	0xff, 0xdb,		//Marker: DQT
157	0x00, 0x84,		//Length: 2*65+2
158	0x00,			//Pq,Tq first table
159	0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
160	0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
161	0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
162	0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
163	0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
164	0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
165	0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
166	0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
167	0x01,			//Pq,Tq second table
168	0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
169	0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
170	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
171	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
172	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
173	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
174	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
175	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63
176};
177
178static const char zr36060_dht[0x1a4] = {
179	0xff, 0xc4,		//Marker: DHT
180	0x01, 0xa2,		//Length: 2*AC, 2*DC
181	0x00,			//DC first table
182	0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
183	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
184	0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
185	0x01,			//DC second table
186	0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
187	0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
188	0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
189	0x10,			//AC first table
190	0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
191	0x05, 0x05, 0x04, 0x04, 0x00, 0x00,
192	0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11,
193	0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
194	0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1,
195	0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24,
196	0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17,
197	0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34,
198	0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
199	0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
200	0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
201	0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
202	0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
203	0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
204	0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
205	0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9,
206	0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8,
207	0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
208	0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
209	0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
210	0xF8, 0xF9, 0xFA,
211	0x11,			//AC second table
212	0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
213	0x07, 0x05, 0x04, 0x04, 0x00, 0x01,
214	0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
215	0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
216	0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
217	0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62,
218	0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25,
219	0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A,
220	0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
221	0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
222	0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
223	0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
224	0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
225	0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
226	0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
227	0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8,
228	0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
229	0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8,
230	0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
231	0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
232	0xF9, 0xFA
233};
234
235/* jpeg baseline setup, this is just fixed in this driver (YUV pictures) */
236#define NO_OF_COMPONENTS          0x3	//Y,U,V
237#define BASELINE_PRECISION        0x8	//MCU size (?)
238static const char zr36060_tq[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };	//table idx's QT
239static const char zr36060_td[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };	//table idx's DC
240static const char zr36060_ta[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };	//table idx's AC
241
242/* horizontal 422 decimation setup (maybe we support 411 or so later, too) */
243static const char zr36060_decimation_h[8] = { 2, 1, 1, 0, 0, 0, 0, 0 };
244static const char zr36060_decimation_v[8] = { 1, 1, 1, 0, 0, 0, 0, 0 };
245
246/*
247 * SOF (start of frame) segment depends on width, height and sampling ratio
248 * of each color component
249 */
250static int zr36060_set_sof(struct zr36060 *ptr)
251{
252	struct zoran *zr = videocodec_to_zoran(ptr->codec);
253	char sof_data[34];	// max. size of register set
254	int i;
255
256	zrdev_dbg(zr, "%s: write SOF (%dx%d, %d components)\n", ptr->name,
257		  ptr->width, ptr->height, NO_OF_COMPONENTS);
258	sof_data[0] = 0xff;
259	sof_data[1] = 0xc0;
260	sof_data[2] = 0x00;
261	sof_data[3] = (3 * NO_OF_COMPONENTS) + 8;
262	sof_data[4] = BASELINE_PRECISION;	// only '8' possible with zr36060
263	sof_data[5] = (ptr->height) >> 8;
264	sof_data[6] = (ptr->height) & 0xff;
265	sof_data[7] = (ptr->width) >> 8;
266	sof_data[8] = (ptr->width) & 0xff;
267	sof_data[9] = NO_OF_COMPONENTS;
268	for (i = 0; i < NO_OF_COMPONENTS; i++) {
269		sof_data[10 + (i * 3)] = i;	// index identifier
270		sof_data[11 + (i * 3)] = (ptr->h_samp_ratio[i] << 4) |
271					 (ptr->v_samp_ratio[i]); // sampling ratios
272		sof_data[12 + (i * 3)] = zr36060_tq[i];	// Q table selection
273	}
274	return zr36060_pushit(ptr, ZR060_SOF_IDX,
275			      (3 * NO_OF_COMPONENTS) + 10, sof_data);
276}
277
278/* SOS (start of scan) segment depends on the used scan components of each color component */
279static int zr36060_set_sos(struct zr36060 *ptr)
280{
281	struct zoran *zr = videocodec_to_zoran(ptr->codec);
282	char sos_data[16];	// max. size of register set
283	int i;
284
285	zrdev_dbg(zr, "%s: write SOS\n", ptr->name);
286	sos_data[0] = 0xff;
287	sos_data[1] = 0xda;
288	sos_data[2] = 0x00;
289	sos_data[3] = 2 + 1 + (2 * NO_OF_COMPONENTS) + 3;
290	sos_data[4] = NO_OF_COMPONENTS;
291	for (i = 0; i < NO_OF_COMPONENTS; i++) {
292		sos_data[5 + (i * 2)] = i;	// index
293		sos_data[6 + (i * 2)] = (zr36060_td[i] << 4) |
294					zr36060_ta[i]; // AC/DC tbl.sel.
295	}
296	sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 2] = 00;	// scan start
297	sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 3] = 0x3f;
298	sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 4] = 00;
299	return zr36060_pushit(ptr, ZR060_SOS_IDX,
300			      4 + 1 + (2 * NO_OF_COMPONENTS) + 3,
301			      sos_data);
302}
303
304/* DRI (define restart interval) */
305static int zr36060_set_dri(struct zr36060 *ptr)
306{
307	struct zoran *zr = videocodec_to_zoran(ptr->codec);
308	char dri_data[6];	// max. size of register set
309
310	zrdev_dbg(zr, "%s: write DRI\n", ptr->name);
311	dri_data[0] = 0xff;
312	dri_data[1] = 0xdd;
313	dri_data[2] = 0x00;
314	dri_data[3] = 0x04;
315	dri_data[4] = (ptr->dri) >> 8;
316	dri_data[5] = (ptr->dri) & 0xff;
317	return zr36060_pushit(ptr, ZR060_DRI_IDX, 6, dri_data);
318}
319
320/* Setup compression/decompression of Zoran's JPEG processor ( see also zoran 36060 manual )
321 * ... sorry for the spaghetti code ...
322 */
323static void zr36060_init(struct zr36060 *ptr)
324{
325	int sum = 0;
326	long bitcnt, tmp;
327	struct zoran *zr = videocodec_to_zoran(ptr->codec);
328
329	if (ptr->mode == CODEC_DO_COMPRESSION) {
330		zrdev_dbg(zr, "%s: COMPRESSION SETUP\n", ptr->name);
331
332		zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SYNC_RST);
333
334		/* 060 communicates with 067 in master mode */
335		zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CODE_MSTR);
336
337		/* Compression with or without variable scale factor */
338		/*FIXME: What about ptr->bitrate_ctrl? */
339		zr36060_write(ptr, ZR060_CMR, ZR060_CMR_COMP | ZR060_CMR_PASS2 | ZR060_CMR_BRB);
340
341		/* Must be zero */
342		zr36060_write(ptr, ZR060_MBZ, 0x00);
343		zr36060_write(ptr, ZR060_TCR_HI, 0x00);
344		zr36060_write(ptr, ZR060_TCR_LO, 0x00);
345
346		/* Disable all IRQs - no DataErr means autoreset */
347		zr36060_write(ptr, ZR060_IMR, 0);
348
349		/* volume control settings */
350		zr36060_write(ptr, ZR060_SF_HI, ptr->scalefact >> 8);
351		zr36060_write(ptr, ZR060_SF_LO, ptr->scalefact & 0xff);
352
353		zr36060_write(ptr, ZR060_AF_HI, 0xff);
354		zr36060_write(ptr, ZR060_AF_M, 0xff);
355		zr36060_write(ptr, ZR060_AF_LO, 0xff);
356
357		/* setup the variable jpeg tables */
358		sum += zr36060_set_sof(ptr);
359		sum += zr36060_set_sos(ptr);
360		sum += zr36060_set_dri(ptr);
361
362/* setup the fixed jpeg tables - maybe variable, though - (see table init section above) */
363		sum += zr36060_pushit(ptr, ZR060_DQT_IDX, sizeof(zr36060_dqt), zr36060_dqt);
364		sum += zr36060_pushit(ptr, ZR060_DHT_IDX, sizeof(zr36060_dht), zr36060_dht);
365		zr36060_write(ptr, ZR060_APP_IDX, 0xff);
366		zr36060_write(ptr, ZR060_APP_IDX + 1, 0xe0 + ptr->app.appn);
367		zr36060_write(ptr, ZR060_APP_IDX + 2, 0x00);
368		zr36060_write(ptr, ZR060_APP_IDX + 3, ptr->app.len + 2);
369		sum += zr36060_pushit(ptr, ZR060_APP_IDX + 4, 60, ptr->app.data) + 4;
370		zr36060_write(ptr, ZR060_COM_IDX, 0xff);
371		zr36060_write(ptr, ZR060_COM_IDX + 1, 0xfe);
372		zr36060_write(ptr, ZR060_COM_IDX + 2, 0x00);
373		zr36060_write(ptr, ZR060_COM_IDX + 3, ptr->com.len + 2);
374		sum += zr36060_pushit(ptr, ZR060_COM_IDX + 4, 60, ptr->com.data) + 4;
375
376		/* setup misc. data for compression (target code sizes) */
377
378		/* size of compressed code to reach without header data */
379		sum = ptr->real_code_vol - sum;
380		bitcnt = sum << 3;	/* need the size in bits */
381
382		tmp = bitcnt >> 16;
383		zrdev_dbg(zr,
384			  "%s: code: csize=%d, tot=%d, bit=%ld, highbits=%ld\n",
385			  ptr->name, sum, ptr->real_code_vol, bitcnt, tmp);
386		zr36060_write(ptr, ZR060_TCV_NET_HI, tmp >> 8);
387		zr36060_write(ptr, ZR060_TCV_NET_MH, tmp & 0xff);
388		tmp = bitcnt & 0xffff;
389		zr36060_write(ptr, ZR060_TCV_NET_ML, tmp >> 8);
390		zr36060_write(ptr, ZR060_TCV_NET_LO, tmp & 0xff);
391
392		bitcnt -= bitcnt >> 7;	// bits without stuffing
393		bitcnt -= ((bitcnt * 5) >> 6);	// bits without eob
394
395		tmp = bitcnt >> 16;
396		zrdev_dbg(zr, "%s: code: nettobit=%ld, highnettobits=%ld\n",
397			  ptr->name, bitcnt, tmp);
398		zr36060_write(ptr, ZR060_TCV_DATA_HI, tmp >> 8);
399		zr36060_write(ptr, ZR060_TCV_DATA_MH, tmp & 0xff);
400		tmp = bitcnt & 0xffff;
401		zr36060_write(ptr, ZR060_TCV_DATA_ML, tmp >> 8);
402		zr36060_write(ptr, ZR060_TCV_DATA_LO, tmp & 0xff);
403
404		/* JPEG markers to be included in the compressed stream */
405		zr36060_write(ptr, ZR060_MER,
406			      ZR060_MER_DQT | ZR060_MER_DHT |
407			      ((ptr->com.len > 0) ? ZR060_MER_COM : 0) |
408			      ((ptr->app.len > 0) ? ZR060_MER_APP : 0));
409
410		/* Setup the Video Frontend */
411		/* Limit pixel range to 16..235 as per CCIR-601 */
412		zr36060_write(ptr, ZR060_VCR, ZR060_VCR_RANGE);
413
414	} else {
415		zrdev_dbg(zr, "%s: EXPANSION SETUP\n", ptr->name);
416
417		zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SYNC_RST);
418
419		/* 060 communicates with 067 in master mode */
420		zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CODE_MSTR);
421
422		/* Decompression */
423		zr36060_write(ptr, ZR060_CMR, 0);
424
425		/* Must be zero */
426		zr36060_write(ptr, ZR060_MBZ, 0x00);
427		zr36060_write(ptr, ZR060_TCR_HI, 0x00);
428		zr36060_write(ptr, ZR060_TCR_LO, 0x00);
429
430		/* Disable all IRQs - no DataErr means autoreset */
431		zr36060_write(ptr, ZR060_IMR, 0);
432
433		/* setup misc. data for expansion */
434		zr36060_write(ptr, ZR060_MER, 0);
435
436/* setup the fixed jpeg tables - maybe variable, though - (see table init section above) */
437		zr36060_pushit(ptr, ZR060_DHT_IDX, sizeof(zr36060_dht), zr36060_dht);
438
439		/* Setup the Video Frontend */
440		//zr36060_write(ptr, ZR060_VCR, ZR060_VCR_FI_EXT);
441		//this doesn't seem right and doesn't work...
442		zr36060_write(ptr, ZR060_VCR, ZR060_VCR_RANGE);
443	}
444
445	/* Load the tables */
446	zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SYNC_RST | ZR060_LOAD_LOAD);
447	zr36060_wait_end(ptr);
448	zrdev_dbg(zr, "%s: Status after table preload: 0x%02x\n",
449		  ptr->name, ptr->status);
450
451	if (ptr->status & ZR060_CFSR_BUSY) {
452		zrdev_err(zr, "%s: init aborted!\n", ptr->name);
453		return;		// something is wrong, its timed out!!!!
454	}
455}
456
457/* =========================================================================
458 * CODEC API FUNCTIONS
459 * this functions are accessed by the master via the API structure
460 * =========================================================================
461 */
462
463/* set compressiion/expansion mode and launches codec -
464 * this should be the last call from the master before starting processing
465 */
466static int zr36060_set_mode(struct videocodec *codec, int mode)
467{
468	struct zr36060 *ptr = (struct zr36060 *)codec->data;
469	struct zoran *zr = videocodec_to_zoran(codec);
470
471	zrdev_dbg(zr, "%s: set_mode %d call\n", ptr->name, mode);
472
473	if (mode != CODEC_DO_EXPANSION && mode != CODEC_DO_COMPRESSION)
474		return -EINVAL;
475
476	ptr->mode = mode;
477	zr36060_init(ptr);
478
479	return 0;
480}
481
482/* set picture size (norm is ignored as the codec doesn't know about it) */
483static int zr36060_set_video(struct videocodec *codec, const struct tvnorm *norm,
484			     struct vfe_settings *cap, struct vfe_polarity *pol)
485{
486	struct zr36060 *ptr = (struct zr36060 *)codec->data;
487	struct zoran *zr = videocodec_to_zoran(codec);
488	u32 reg;
489	int size;
490
491	zrdev_dbg(zr, "%s: set_video %d/%d-%dx%d (%%%d) call\n", ptr->name,
492		  cap->x, cap->y, cap->width, cap->height, cap->decimation);
493
494	/* if () return -EINVAL;
495	 * trust the master driver that it knows what it does - so
496	 * we allow invalid startx/y and norm for now ...
497	 */
498	ptr->width = cap->width / (cap->decimation & 0xff);
499	ptr->height = cap->height / (cap->decimation >> 8);
500
501	zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SYNC_RST);
502
503	/* Note that VSPol/HSPol bits in zr36060 have the opposite
504	 * meaning of their zr360x7 counterparts with the same names
505	 * N.b. for VSPol this is only true if FIVEdge = 0 (default,
506	 * left unchanged here - in accordance with datasheet).
507	 */
508	reg = (!pol->vsync_pol ? ZR060_VPR_VS_POL : 0)
509	    | (!pol->hsync_pol ? ZR060_VPR_HS_POL : 0)
510	    | (pol->field_pol ? ZR060_VPR_FI_POL : 0)
511	    | (pol->blank_pol ? ZR060_VPR_BL_POL : 0)
512	    | (pol->subimg_pol ? ZR060_VPR_S_IMG_POL : 0)
513	    | (pol->poe_pol ? ZR060_VPR_POE_POL : 0)
514	    | (pol->pvalid_pol ? ZR060_VPR_P_VAL_POL : 0)
515	    | (pol->vclk_pol ? ZR060_VPR_VCLK_POL : 0);
516	zr36060_write(ptr, ZR060_VPR, reg);
517
518	reg = 0;
519	switch (cap->decimation & 0xff) {
520	default:
521	case 1:
522		break;
523
524	case 2:
525		reg |= ZR060_SR_H_SCALE2;
526		break;
527
528	case 4:
529		reg |= ZR060_SR_H_SCALE4;
530		break;
531	}
532
533	switch (cap->decimation >> 8) {
534	default:
535	case 1:
536		break;
537
538	case 2:
539		reg |= ZR060_SR_V_SCALE;
540		break;
541	}
542	zr36060_write(ptr, ZR060_SR, reg);
543
544	zr36060_write(ptr, ZR060_BCR_Y, 0x00);
545	zr36060_write(ptr, ZR060_BCR_U, 0x80);
546	zr36060_write(ptr, ZR060_BCR_V, 0x80);
547
548	/* sync generator */
549
550	reg = norm->ht - 1;	/* Vtotal */
551	zr36060_write(ptr, ZR060_SGR_VTOTAL_HI, (reg >> 8) & 0xff);
552	zr36060_write(ptr, ZR060_SGR_VTOTAL_LO, (reg >> 0) & 0xff);
553
554	reg = norm->wt - 1;	/* Htotal */
555	zr36060_write(ptr, ZR060_SGR_HTOTAL_HI, (reg >> 8) & 0xff);
556	zr36060_write(ptr, ZR060_SGR_HTOTAL_LO, (reg >> 0) & 0xff);
557
558	reg = 6 - 1;		/* VsyncSize */
559	zr36060_write(ptr, ZR060_SGR_VSYNC, reg);
560
561	reg = 68;
562	zr36060_write(ptr, ZR060_SGR_HSYNC, reg);
563
564	reg = norm->v_start - 1;	/* BVstart */
565	zr36060_write(ptr, ZR060_SGR_BVSTART, reg);
566
567	reg += norm->ha / 2;	/* BVend */
568	zr36060_write(ptr, ZR060_SGR_BVEND_HI, (reg >> 8) & 0xff);
569	zr36060_write(ptr, ZR060_SGR_BVEND_LO, (reg >> 0) & 0xff);
570
571	reg = norm->h_start - 1;	/* BHstart */
572	zr36060_write(ptr, ZR060_SGR_BHSTART, reg);
573
574	reg += norm->wa;	/* BHend */
575	zr36060_write(ptr, ZR060_SGR_BHEND_HI, (reg >> 8) & 0xff);
576	zr36060_write(ptr, ZR060_SGR_BHEND_LO, (reg >> 0) & 0xff);
577
578	/* active area */
579	reg = cap->y + norm->v_start;	/* Vstart */
580	zr36060_write(ptr, ZR060_AAR_VSTART_HI, (reg >> 8) & 0xff);
581	zr36060_write(ptr, ZR060_AAR_VSTART_LO, (reg >> 0) & 0xff);
582
583	reg += cap->height;	/* Vend */
584	zr36060_write(ptr, ZR060_AAR_VEND_HI, (reg >> 8) & 0xff);
585	zr36060_write(ptr, ZR060_AAR_VEND_LO, (reg >> 0) & 0xff);
586
587	reg = cap->x + norm->h_start;	/* Hstart */
588	zr36060_write(ptr, ZR060_AAR_HSTART_HI, (reg >> 8) & 0xff);
589	zr36060_write(ptr, ZR060_AAR_HSTART_LO, (reg >> 0) & 0xff);
590
591	reg += cap->width;	/* Hend */
592	zr36060_write(ptr, ZR060_AAR_HEND_HI, (reg >> 8) & 0xff);
593	zr36060_write(ptr, ZR060_AAR_HEND_LO, (reg >> 0) & 0xff);
594
595	/* subimage area */
596	reg = norm->v_start - 4;	/* SVstart */
597	zr36060_write(ptr, ZR060_SWR_VSTART_HI, (reg >> 8) & 0xff);
598	zr36060_write(ptr, ZR060_SWR_VSTART_LO, (reg >> 0) & 0xff);
599
600	reg += norm->ha / 2 + 8;	/* SVend */
601	zr36060_write(ptr, ZR060_SWR_VEND_HI, (reg >> 8) & 0xff);
602	zr36060_write(ptr, ZR060_SWR_VEND_LO, (reg >> 0) & 0xff);
603
604	reg = norm->h_start /*+ 64 */  - 4;	/* SHstart */
605	zr36060_write(ptr, ZR060_SWR_HSTART_HI, (reg >> 8) & 0xff);
606	zr36060_write(ptr, ZR060_SWR_HSTART_LO, (reg >> 0) & 0xff);
607
608	reg += norm->wa + 8;	/* SHend */
609	zr36060_write(ptr, ZR060_SWR_HEND_HI, (reg >> 8) & 0xff);
610	zr36060_write(ptr, ZR060_SWR_HEND_LO, (reg >> 0) & 0xff);
611
612	size = ptr->width * ptr->height;
613	/* Target compressed field size in bits: */
614	size = size * 16;	/* uncompressed size in bits */
615	/* (Ronald) by default, quality = 100 is a compression
616	 * ratio 1:2. Setting low_bitrate (insmod option) sets
617	 * it to 1:4 (instead of 1:2, zr36060 max) as limit because the
618	 * buz can't handle more at decimation=1... Use low_bitrate if
619	 * you have a Buz, unless you know what you're doing
620	 */
621	size = size * cap->quality / (low_bitrate ? 400 : 200);
622	/* Lower limit (arbitrary, 1 KB) */
623	if (size < 8192)
624		size = 8192;
625	/* Upper limit: 7/8 of the code buffers */
626	if (size > ptr->total_code_vol * 7)
627		size = ptr->total_code_vol * 7;
628
629	ptr->real_code_vol = size >> 3;	/* in bytes */
630
631	/* the MBCVR is the *maximum* block volume, according to the
632	 * JPEG ISO specs, this shouldn't be used, since that allows
633	 * for the best encoding quality. So set it to it's max value
634	 */
635	reg = ptr->max_block_vol;
636	zr36060_write(ptr, ZR060_MBCVR, reg);
637
638	return 0;
639}
640
641/* additional control functions */
642static int zr36060_control(struct videocodec *codec, int type, int size, void *data)
643{
644	struct zr36060 *ptr = (struct zr36060 *)codec->data;
645	struct zoran *zr = videocodec_to_zoran(codec);
646	int *ival = (int *)data;
647
648	zrdev_dbg(zr, "%s: control %d call with %d byte\n", ptr->name, type,
649		  size);
650
651	switch (type) {
652	case CODEC_G_STATUS:	/* get last status */
653		if (size != sizeof(int))
654			return -EFAULT;
655		zr36060_read_status(ptr);
656		*ival = ptr->status;
657		break;
658
659	case CODEC_G_CODEC_MODE:
660		if (size != sizeof(int))
661			return -EFAULT;
662		*ival = CODEC_MODE_BJPG;
663		break;
664
665	case CODEC_S_CODEC_MODE:
666		if (size != sizeof(int))
667			return -EFAULT;
668		if (*ival != CODEC_MODE_BJPG)
669			return -EINVAL;
670		/* not needed, do nothing */
671		return 0;
672
673	case CODEC_G_VFE:
674	case CODEC_S_VFE:
675		/* not needed, do nothing */
676		return 0;
677
678	case CODEC_S_MMAP:
679		/* not available, give an error */
680		return -ENXIO;
681
682	case CODEC_G_JPEG_TDS_BYTE:	/* get target volume in byte */
683		if (size != sizeof(int))
684			return -EFAULT;
685		*ival = ptr->total_code_vol;
686		break;
687
688	case CODEC_S_JPEG_TDS_BYTE:	/* get target volume in byte */
689		if (size != sizeof(int))
690			return -EFAULT;
691		ptr->total_code_vol = *ival;
692		ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
693		break;
694
695	case CODEC_G_JPEG_SCALE:	/* get scaling factor */
696		if (size != sizeof(int))
697			return -EFAULT;
698		*ival = zr36060_read_scalefactor(ptr);
699		break;
700
701	case CODEC_S_JPEG_SCALE:	/* set scaling factor */
702		if (size != sizeof(int))
703			return -EFAULT;
704		ptr->scalefact = *ival;
705		break;
706
707	case CODEC_G_JPEG_APP_DATA: {	/* get appn marker data */
708		struct jpeg_app_marker *app = data;
709
710		if (size != sizeof(struct jpeg_app_marker))
711			return -EFAULT;
712
713		*app = ptr->app;
714		break;
715	}
716
717	case CODEC_S_JPEG_APP_DATA: {	/* set appn marker data */
718		struct jpeg_app_marker *app = data;
719
720		if (size != sizeof(struct jpeg_app_marker))
721			return -EFAULT;
722
723		ptr->app = *app;
724		break;
725	}
726
727	case CODEC_G_JPEG_COM_DATA: {	/* get comment marker data */
728		struct jpeg_com_marker *com = data;
729
730		if (size != sizeof(struct jpeg_com_marker))
731			return -EFAULT;
732
733		*com = ptr->com;
734		break;
735	}
736
737	case CODEC_S_JPEG_COM_DATA: {	/* set comment marker data */
738		struct jpeg_com_marker *com = data;
739
740		if (size != sizeof(struct jpeg_com_marker))
741			return -EFAULT;
742
743		ptr->com = *com;
744		break;
745	}
746
747	default:
748		return -EINVAL;
749	}
750
751	return size;
752}
753
754/* =========================================================================
755 * Exit and unregister function:
756 * Deinitializes Zoran's JPEG processor
757 * =========================================================================
758 */
759static int zr36060_unset(struct videocodec *codec)
760{
761	struct zr36060 *ptr = codec->data;
762	struct zoran *zr = videocodec_to_zoran(codec);
763
764	if (ptr) {
765		/* do wee need some codec deinit here, too ???? */
766
767		zrdev_dbg(zr, "%s: finished codec #%d\n", ptr->name, ptr->num);
768		kfree(ptr);
769		codec->data = NULL;
770
771		zr36060_codecs--;
772		return 0;
773	}
774
775	return -EFAULT;
776}
777
778/* =========================================================================
779 * Setup and registry function:
780 * Initializes Zoran's JPEG processor
781 * Also sets pixel size, average code size, mode (compr./decompr.)
782 * (the given size is determined by the processor with the video interface)
783 * =========================================================================
784 */
785static int zr36060_setup(struct videocodec *codec)
786{
787	struct zr36060 *ptr;
788	struct zoran *zr = videocodec_to_zoran(codec);
789	int res;
790
791	zrdev_dbg(zr, "zr36060: initializing MJPEG subsystem #%d.\n",
792		  zr36060_codecs);
793
794	if (zr36060_codecs == MAX_CODECS) {
795		zrdev_err(zr, "zr36060: Can't attach more codecs!\n");
796		return -ENOSPC;
797	}
798	//mem structure init
799	ptr = kzalloc(sizeof(*ptr), GFP_KERNEL);
800	codec->data = ptr;
801	if (!ptr)
802		return -ENOMEM;
803
804	snprintf(ptr->name, sizeof(ptr->name), "zr36060[%d]", zr36060_codecs);
805	ptr->num = zr36060_codecs++;
806	ptr->codec = codec;
807
808	//testing
809	res = zr36060_basic_test(ptr);
810	if (res < 0) {
811		zr36060_unset(codec);
812		return res;
813	}
814	//final setup
815	memcpy(ptr->h_samp_ratio, zr36060_decimation_h, 8);
816	memcpy(ptr->v_samp_ratio, zr36060_decimation_v, 8);
817
818	ptr->bitrate_ctrl = 0;	/* 0 or 1 - fixed file size flag (what is the difference?) */
819	ptr->mode = CODEC_DO_COMPRESSION;
820	ptr->width = 384;
821	ptr->height = 288;
822	ptr->total_code_vol = 16000;	/* CHECKME */
823	ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
824	ptr->max_block_vol = 240;	/* CHECKME, was 120 is 240 */
825	ptr->scalefact = 0x100;
826	ptr->dri = 1;		/* CHECKME, was 8 is 1 */
827
828	/* by default, no COM or APP markers - app should set those */
829	ptr->com.len = 0;
830	ptr->app.appn = 0;
831	ptr->app.len = 0;
832
833	zr36060_init(ptr);
834
835	zrdev_info(zr, "%s: codec attached and running\n", ptr->name);
836
837	return 0;
838}
839
840static const struct videocodec zr36060_codec = {
841	.name = "zr36060",
842	.magic = 0L,		// magic not used
843	.flags =
844	    CODEC_FLAG_JPEG | CODEC_FLAG_HARDWARE | CODEC_FLAG_ENCODER |
845	    CODEC_FLAG_DECODER | CODEC_FLAG_VFE,
846	.type = CODEC_TYPE_ZR36060,
847	.setup = zr36060_setup,	// functionality
848	.unset = zr36060_unset,
849	.set_mode = zr36060_set_mode,
850	.set_video = zr36060_set_video,
851	.control = zr36060_control,
852	// others are not used
853};
854
855int zr36060_init_module(void)
856{
857	zr36060_codecs = 0;
858	return videocodec_register(&zr36060_codec);
859}
860
861void zr36060_cleanup_module(void)
862{
863	if (zr36060_codecs) {
864		pr_debug("zr36060: something's wrong - %d codecs left somehow.\n",
865			 zr36060_codecs);
866	}
867
868	/* however, we can't just stay alive */
869	videocodec_unregister(&zr36060_codec);
870}
871