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(codec: 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(codec: 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, reg: 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, reg: 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(codec: 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(codec: 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(codec: 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, reg: startreg++, value: 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(codec: 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 len: (3 * NO_OF_COMPONENTS) + 10, data: 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(codec: 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 len: 4 + 1 + (2 * NO_OF_COMPONENTS) + 3,
301 data: 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(codec: 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, len: 6, data: 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(codec: 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, value: 0x00);
343 zr36060_write(ptr, ZR060_TCR_HI, value: 0x00);
344 zr36060_write(ptr, ZR060_TCR_LO, value: 0x00);
345
346 /* Disable all IRQs - no DataErr means autoreset */
347 zr36060_write(ptr, ZR060_IMR, value: 0);
348
349 /* volume control settings */
350 zr36060_write(ptr, ZR060_SF_HI, value: ptr->scalefact >> 8);
351 zr36060_write(ptr, ZR060_SF_LO, value: ptr->scalefact & 0xff);
352
353 zr36060_write(ptr, ZR060_AF_HI, value: 0xff);
354 zr36060_write(ptr, ZR060_AF_M, value: 0xff);
355 zr36060_write(ptr, ZR060_AF_LO, value: 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, len: sizeof(zr36060_dqt), data: zr36060_dqt);
364 sum += zr36060_pushit(ptr, ZR060_DHT_IDX, len: sizeof(zr36060_dht), data: zr36060_dht);
365 zr36060_write(ptr, ZR060_APP_IDX, value: 0xff);
366 zr36060_write(ptr, ZR060_APP_IDX + 1, value: 0xe0 + ptr->app.appn);
367 zr36060_write(ptr, ZR060_APP_IDX + 2, value: 0x00);
368 zr36060_write(ptr, ZR060_APP_IDX + 3, value: ptr->app.len + 2);
369 sum += zr36060_pushit(ptr, ZR060_APP_IDX + 4, len: 60, data: ptr->app.data) + 4;
370 zr36060_write(ptr, ZR060_COM_IDX, value: 0xff);
371 zr36060_write(ptr, ZR060_COM_IDX + 1, value: 0xfe);
372 zr36060_write(ptr, ZR060_COM_IDX + 2, value: 0x00);
373 zr36060_write(ptr, ZR060_COM_IDX + 3, value: ptr->com.len + 2);
374 sum += zr36060_pushit(ptr, ZR060_COM_IDX + 4, len: 60, data: 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, value: tmp >> 8);
387 zr36060_write(ptr, ZR060_TCV_NET_MH, value: tmp & 0xff);
388 tmp = bitcnt & 0xffff;
389 zr36060_write(ptr, ZR060_TCV_NET_ML, value: tmp >> 8);
390 zr36060_write(ptr, ZR060_TCV_NET_LO, value: 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, value: tmp >> 8);
399 zr36060_write(ptr, ZR060_TCV_DATA_MH, value: tmp & 0xff);
400 tmp = bitcnt & 0xffff;
401 zr36060_write(ptr, ZR060_TCV_DATA_ML, value: tmp >> 8);
402 zr36060_write(ptr, ZR060_TCV_DATA_LO, value: 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, value: 0);
424
425 /* Must be zero */
426 zr36060_write(ptr, ZR060_MBZ, value: 0x00);
427 zr36060_write(ptr, ZR060_TCR_HI, value: 0x00);
428 zr36060_write(ptr, ZR060_TCR_LO, value: 0x00);
429
430 /* Disable all IRQs - no DataErr means autoreset */
431 zr36060_write(ptr, ZR060_IMR, value: 0);
432
433 /* setup misc. data for expansion */
434 zr36060_write(ptr, ZR060_MER, value: 0);
435
436/* setup the fixed jpeg tables - maybe variable, though - (see table init section above) */
437 zr36060_pushit(ptr, ZR060_DHT_IDX, len: sizeof(zr36060_dht), data: 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, value: 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, value: reg);
543
544 zr36060_write(ptr, ZR060_BCR_Y, value: 0x00);
545 zr36060_write(ptr, ZR060_BCR_U, value: 0x80);
546 zr36060_write(ptr, ZR060_BCR_V, value: 0x80);
547
548 /* sync generator */
549
550 reg = norm->ht - 1; /* Vtotal */
551 zr36060_write(ptr, ZR060_SGR_VTOTAL_HI, value: (reg >> 8) & 0xff);
552 zr36060_write(ptr, ZR060_SGR_VTOTAL_LO, value: (reg >> 0) & 0xff);
553
554 reg = norm->wt - 1; /* Htotal */
555 zr36060_write(ptr, ZR060_SGR_HTOTAL_HI, value: (reg >> 8) & 0xff);
556 zr36060_write(ptr, ZR060_SGR_HTOTAL_LO, value: (reg >> 0) & 0xff);
557
558 reg = 6 - 1; /* VsyncSize */
559 zr36060_write(ptr, ZR060_SGR_VSYNC, value: reg);
560
561 reg = 68;
562 zr36060_write(ptr, ZR060_SGR_HSYNC, value: reg);
563
564 reg = norm->v_start - 1; /* BVstart */
565 zr36060_write(ptr, ZR060_SGR_BVSTART, value: reg);
566
567 reg += norm->ha / 2; /* BVend */
568 zr36060_write(ptr, ZR060_SGR_BVEND_HI, value: (reg >> 8) & 0xff);
569 zr36060_write(ptr, ZR060_SGR_BVEND_LO, value: (reg >> 0) & 0xff);
570
571 reg = norm->h_start - 1; /* BHstart */
572 zr36060_write(ptr, ZR060_SGR_BHSTART, value: reg);
573
574 reg += norm->wa; /* BHend */
575 zr36060_write(ptr, ZR060_SGR_BHEND_HI, value: (reg >> 8) & 0xff);
576 zr36060_write(ptr, ZR060_SGR_BHEND_LO, value: (reg >> 0) & 0xff);
577
578 /* active area */
579 reg = cap->y + norm->v_start; /* Vstart */
580 zr36060_write(ptr, ZR060_AAR_VSTART_HI, value: (reg >> 8) & 0xff);
581 zr36060_write(ptr, ZR060_AAR_VSTART_LO, value: (reg >> 0) & 0xff);
582
583 reg += cap->height; /* Vend */
584 zr36060_write(ptr, ZR060_AAR_VEND_HI, value: (reg >> 8) & 0xff);
585 zr36060_write(ptr, ZR060_AAR_VEND_LO, value: (reg >> 0) & 0xff);
586
587 reg = cap->x + norm->h_start; /* Hstart */
588 zr36060_write(ptr, ZR060_AAR_HSTART_HI, value: (reg >> 8) & 0xff);
589 zr36060_write(ptr, ZR060_AAR_HSTART_LO, value: (reg >> 0) & 0xff);
590
591 reg += cap->width; /* Hend */
592 zr36060_write(ptr, ZR060_AAR_HEND_HI, value: (reg >> 8) & 0xff);
593 zr36060_write(ptr, ZR060_AAR_HEND_LO, value: (reg >> 0) & 0xff);
594
595 /* subimage area */
596 reg = norm->v_start - 4; /* SVstart */
597 zr36060_write(ptr, ZR060_SWR_VSTART_HI, value: (reg >> 8) & 0xff);
598 zr36060_write(ptr, ZR060_SWR_VSTART_LO, value: (reg >> 0) & 0xff);
599
600 reg += norm->ha / 2 + 8; /* SVend */
601 zr36060_write(ptr, ZR060_SWR_VEND_HI, value: (reg >> 8) & 0xff);
602 zr36060_write(ptr, ZR060_SWR_VEND_LO, value: (reg >> 0) & 0xff);
603
604 reg = norm->h_start /*+ 64 */ - 4; /* SHstart */
605 zr36060_write(ptr, ZR060_SWR_HSTART_HI, value: (reg >> 8) & 0xff);
606 zr36060_write(ptr, ZR060_SWR_HSTART_LO, value: (reg >> 0) & 0xff);
607
608 reg += norm->wa + 8; /* SHend */
609 zr36060_write(ptr, ZR060_SWR_HEND_HI, value: (reg >> 8) & 0xff);
610 zr36060_write(ptr, ZR060_SWR_HEND_LO, value: (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, value: 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(objp: 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(size: sizeof(*ptr), GFP_KERNEL);
800 codec->data = ptr;
801 if (!ptr)
802 return -ENOMEM;
803
804 snprintf(buf: ptr->name, size: sizeof(ptr->name), fmt: "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(codec: &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(codec: &zr36060_codec);
870}
871

source code of linux/drivers/media/pci/zoran/zr36060.c