1
2
3
4
5
6
7
8
9
10
11
12
13
14#include <linux/device.h>
15#include <linux/mm.h>
16#include <linux/module.h>
17#include <linux/mutex.h>
18#include <linux/uaccess.h>
19
20#include "isp.h"
21#include "ispreg.h"
22#include "isppreview.h"
23
24
25static const struct omap3isp_prev_rgbtorgb flr_rgb2rgb = {
26 {
27 {0x01E2, 0x0F30, 0x0FEE},
28 {0x0F9B, 0x01AC, 0x0FB9},
29 {0x0FE0, 0x0EC0, 0x0260}
30 },
31 {0x0000, 0x0000, 0x0000}
32};
33
34
35static const struct omap3isp_prev_csc flr_prev_csc = {
36 {
37 {66, 129, 25},
38 {-38, -75, 112},
39 {112, -94 , -18}
40 },
41 {0x0, 0x0, 0x0}
42};
43
44
45#define FLR_CFA_GRADTHRS_HORZ 0x28
46#define FLR_CFA_GRADTHRS_VERT 0x28
47
48
49#define FLR_CSUP_GAIN 0x0D
50#define FLR_CSUP_THRES 0xEB
51
52
53#define FLR_NF_STRGTH 0x03
54
55
56#define FLR_WBAL_DGAIN 0x100
57#define FLR_WBAL_COEF 0x20
58
59
60#define FLR_BLKADJ_BLUE 0x0
61#define FLR_BLKADJ_GREEN 0x0
62#define FLR_BLKADJ_RED 0x0
63
64#define DEF_DETECT_CORRECT_VAL 0xe
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96#define PREV_MARGIN_LEFT 6
97#define PREV_MARGIN_RIGHT 4
98#define PREV_MARGIN_TOP 2
99#define PREV_MARGIN_BOTTOM 2
100
101#define PREV_MIN_IN_WIDTH 64
102#define PREV_MIN_IN_HEIGHT 8
103#define PREV_MAX_IN_HEIGHT 16384
104
105#define PREV_MIN_OUT_WIDTH 0
106#define PREV_MIN_OUT_HEIGHT 0
107#define PREV_MAX_OUT_WIDTH_REV_1 1280
108#define PREV_MAX_OUT_WIDTH_REV_2 3300
109#define PREV_MAX_OUT_WIDTH_REV_15 4096
110
111
112
113
114
115
116
117
118
119
120static u32 cfa_coef_table[4][OMAP3ISP_PREV_CFA_BLK_SIZE] = {
121#include "cfa_coef_table.h"
122};
123
124
125
126
127static u32 gamma_table[] = {
128#include "gamma_table.h"
129};
130
131
132
133
134static u32 noise_filter_table[] = {
135#include "noise_filter_table.h"
136};
137
138
139
140
141static u32 luma_enhance_table[] = {
142#include "luma_enhance_table.h"
143};
144
145
146
147
148static void
149preview_config_luma_enhancement(struct isp_prev_device *prev,
150 const struct prev_params *params)
151{
152 struct isp_device *isp = to_isp_device(prev);
153 const struct omap3isp_prev_luma *yt = ¶ms->luma;
154 unsigned int i;
155
156 isp_reg_writel(isp, ISPPRV_YENH_TABLE_ADDR,
157 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
158 for (i = 0; i < OMAP3ISP_PREV_YENH_TBL_SIZE; i++) {
159 isp_reg_writel(isp, yt->table[i],
160 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
161 }
162}
163
164
165
166
167static void
168preview_enable_luma_enhancement(struct isp_prev_device *prev, bool enable)
169{
170 struct isp_device *isp = to_isp_device(prev);
171
172 if (enable)
173 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
174 ISPPRV_PCR_YNENHEN);
175 else
176 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
177 ISPPRV_PCR_YNENHEN);
178}
179
180
181
182
183static void preview_enable_invalaw(struct isp_prev_device *prev, bool enable)
184{
185 struct isp_device *isp = to_isp_device(prev);
186
187 if (enable)
188 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
189 ISPPRV_PCR_INVALAW);
190 else
191 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
192 ISPPRV_PCR_INVALAW);
193}
194
195
196
197
198static void preview_config_hmed(struct isp_prev_device *prev,
199 const struct prev_params *params)
200{
201 struct isp_device *isp = to_isp_device(prev);
202 const struct omap3isp_prev_hmed *hmed = ¶ms->hmed;
203
204 isp_reg_writel(isp, (hmed->odddist == 1 ? 0 : ISPPRV_HMED_ODDDIST) |
205 (hmed->evendist == 1 ? 0 : ISPPRV_HMED_EVENDIST) |
206 (hmed->thres << ISPPRV_HMED_THRESHOLD_SHIFT),
207 OMAP3_ISP_IOMEM_PREV, ISPPRV_HMED);
208}
209
210
211
212
213static void preview_enable_hmed(struct isp_prev_device *prev, bool enable)
214{
215 struct isp_device *isp = to_isp_device(prev);
216
217 if (enable)
218 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
219 ISPPRV_PCR_HMEDEN);
220 else
221 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
222 ISPPRV_PCR_HMEDEN);
223}
224
225
226
227
228
229
230
231
232
233static void preview_config_cfa(struct isp_prev_device *prev,
234 const struct prev_params *params)
235{
236 static const unsigned int cfa_coef_order[4][4] = {
237 { 0, 1, 2, 3 },
238 { 1, 0, 3, 2 },
239 { 2, 3, 0, 1 },
240 { 3, 2, 1, 0 },
241 };
242 const unsigned int *order = cfa_coef_order[prev->params.cfa_order];
243 const struct omap3isp_prev_cfa *cfa = ¶ms->cfa;
244 struct isp_device *isp = to_isp_device(prev);
245 unsigned int i;
246 unsigned int j;
247
248 isp_reg_writel(isp,
249 (cfa->gradthrs_vert << ISPPRV_CFA_GRADTH_VER_SHIFT) |
250 (cfa->gradthrs_horz << ISPPRV_CFA_GRADTH_HOR_SHIFT),
251 OMAP3_ISP_IOMEM_PREV, ISPPRV_CFA);
252
253 isp_reg_writel(isp, ISPPRV_CFA_TABLE_ADDR,
254 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
255
256 for (i = 0; i < 4; ++i) {
257 const __u32 *block = cfa->table[order[i]];
258
259 for (j = 0; j < OMAP3ISP_PREV_CFA_BLK_SIZE; ++j)
260 isp_reg_writel(isp, block[j], OMAP3_ISP_IOMEM_PREV,
261 ISPPRV_SET_TBL_DATA);
262 }
263}
264
265
266
267
268static void
269preview_config_chroma_suppression(struct isp_prev_device *prev,
270 const struct prev_params *params)
271{
272 struct isp_device *isp = to_isp_device(prev);
273 const struct omap3isp_prev_csup *cs = ¶ms->csup;
274
275 isp_reg_writel(isp,
276 cs->gain | (cs->thres << ISPPRV_CSUP_THRES_SHIFT) |
277 (cs->hypf_en << ISPPRV_CSUP_HPYF_SHIFT),
278 OMAP3_ISP_IOMEM_PREV, ISPPRV_CSUP);
279}
280
281
282
283
284static void
285preview_enable_chroma_suppression(struct isp_prev_device *prev, bool enable)
286{
287 struct isp_device *isp = to_isp_device(prev);
288
289 if (enable)
290 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
291 ISPPRV_PCR_SUPEN);
292 else
293 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
294 ISPPRV_PCR_SUPEN);
295}
296
297
298
299
300
301
302static void
303preview_config_whitebalance(struct isp_prev_device *prev,
304 const struct prev_params *params)
305{
306 struct isp_device *isp = to_isp_device(prev);
307 const struct omap3isp_prev_wbal *wbal = ¶ms->wbal;
308 u32 val;
309
310 isp_reg_writel(isp, wbal->dgain, OMAP3_ISP_IOMEM_PREV, ISPPRV_WB_DGAIN);
311
312 val = wbal->coef0 << ISPPRV_WBGAIN_COEF0_SHIFT;
313 val |= wbal->coef1 << ISPPRV_WBGAIN_COEF1_SHIFT;
314 val |= wbal->coef2 << ISPPRV_WBGAIN_COEF2_SHIFT;
315 val |= wbal->coef3 << ISPPRV_WBGAIN_COEF3_SHIFT;
316 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_WBGAIN);
317
318 isp_reg_writel(isp,
319 ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N0_0_SHIFT |
320 ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N0_1_SHIFT |
321 ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N0_2_SHIFT |
322 ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N0_3_SHIFT |
323 ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N1_0_SHIFT |
324 ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N1_1_SHIFT |
325 ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N1_2_SHIFT |
326 ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N1_3_SHIFT |
327 ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N2_0_SHIFT |
328 ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N2_1_SHIFT |
329 ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N2_2_SHIFT |
330 ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N2_3_SHIFT |
331 ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N3_0_SHIFT |
332 ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N3_1_SHIFT |
333 ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N3_2_SHIFT |
334 ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N3_3_SHIFT,
335 OMAP3_ISP_IOMEM_PREV, ISPPRV_WBSEL);
336}
337
338
339
340
341static void
342preview_config_blkadj(struct isp_prev_device *prev,
343 const struct prev_params *params)
344{
345 struct isp_device *isp = to_isp_device(prev);
346 const struct omap3isp_prev_blkadj *blkadj = ¶ms->blkadj;
347
348 isp_reg_writel(isp, (blkadj->blue << ISPPRV_BLKADJOFF_B_SHIFT) |
349 (blkadj->green << ISPPRV_BLKADJOFF_G_SHIFT) |
350 (blkadj->red << ISPPRV_BLKADJOFF_R_SHIFT),
351 OMAP3_ISP_IOMEM_PREV, ISPPRV_BLKADJOFF);
352}
353
354
355
356
357static void
358preview_config_rgb_blending(struct isp_prev_device *prev,
359 const struct prev_params *params)
360{
361 struct isp_device *isp = to_isp_device(prev);
362 const struct omap3isp_prev_rgbtorgb *rgbrgb = ¶ms->rgb2rgb;
363 u32 val;
364
365 val = (rgbrgb->matrix[0][0] & 0xfff) << ISPPRV_RGB_MAT1_MTX_RR_SHIFT;
366 val |= (rgbrgb->matrix[0][1] & 0xfff) << ISPPRV_RGB_MAT1_MTX_GR_SHIFT;
367 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT1);
368
369 val = (rgbrgb->matrix[0][2] & 0xfff) << ISPPRV_RGB_MAT2_MTX_BR_SHIFT;
370 val |= (rgbrgb->matrix[1][0] & 0xfff) << ISPPRV_RGB_MAT2_MTX_RG_SHIFT;
371 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT2);
372
373 val = (rgbrgb->matrix[1][1] & 0xfff) << ISPPRV_RGB_MAT3_MTX_GG_SHIFT;
374 val |= (rgbrgb->matrix[1][2] & 0xfff) << ISPPRV_RGB_MAT3_MTX_BG_SHIFT;
375 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT3);
376
377 val = (rgbrgb->matrix[2][0] & 0xfff) << ISPPRV_RGB_MAT4_MTX_RB_SHIFT;
378 val |= (rgbrgb->matrix[2][1] & 0xfff) << ISPPRV_RGB_MAT4_MTX_GB_SHIFT;
379 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT4);
380
381 val = (rgbrgb->matrix[2][2] & 0xfff) << ISPPRV_RGB_MAT5_MTX_BB_SHIFT;
382 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT5);
383
384 val = (rgbrgb->offset[0] & 0x3ff) << ISPPRV_RGB_OFF1_MTX_OFFR_SHIFT;
385 val |= (rgbrgb->offset[1] & 0x3ff) << ISPPRV_RGB_OFF1_MTX_OFFG_SHIFT;
386 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF1);
387
388 val = (rgbrgb->offset[2] & 0x3ff) << ISPPRV_RGB_OFF2_MTX_OFFB_SHIFT;
389 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF2);
390}
391
392
393
394
395static void
396preview_config_csc(struct isp_prev_device *prev,
397 const struct prev_params *params)
398{
399 struct isp_device *isp = to_isp_device(prev);
400 const struct omap3isp_prev_csc *csc = ¶ms->csc;
401 u32 val;
402
403 val = (csc->matrix[0][0] & 0x3ff) << ISPPRV_CSC0_RY_SHIFT;
404 val |= (csc->matrix[0][1] & 0x3ff) << ISPPRV_CSC0_GY_SHIFT;
405 val |= (csc->matrix[0][2] & 0x3ff) << ISPPRV_CSC0_BY_SHIFT;
406 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC0);
407
408 val = (csc->matrix[1][0] & 0x3ff) << ISPPRV_CSC1_RCB_SHIFT;
409 val |= (csc->matrix[1][1] & 0x3ff) << ISPPRV_CSC1_GCB_SHIFT;
410 val |= (csc->matrix[1][2] & 0x3ff) << ISPPRV_CSC1_BCB_SHIFT;
411 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC1);
412
413 val = (csc->matrix[2][0] & 0x3ff) << ISPPRV_CSC2_RCR_SHIFT;
414 val |= (csc->matrix[2][1] & 0x3ff) << ISPPRV_CSC2_GCR_SHIFT;
415 val |= (csc->matrix[2][2] & 0x3ff) << ISPPRV_CSC2_BCR_SHIFT;
416 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC2);
417
418 val = (csc->offset[0] & 0xff) << ISPPRV_CSC_OFFSET_Y_SHIFT;
419 val |= (csc->offset[1] & 0xff) << ISPPRV_CSC_OFFSET_CB_SHIFT;
420 val |= (csc->offset[2] & 0xff) << ISPPRV_CSC_OFFSET_CR_SHIFT;
421 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC_OFFSET);
422}
423
424
425
426
427static void
428preview_config_yc_range(struct isp_prev_device *prev,
429 const struct prev_params *params)
430{
431 struct isp_device *isp = to_isp_device(prev);
432 const struct omap3isp_prev_yclimit *yc = ¶ms->yclimit;
433
434 isp_reg_writel(isp,
435 yc->maxC << ISPPRV_SETUP_YC_MAXC_SHIFT |
436 yc->maxY << ISPPRV_SETUP_YC_MAXY_SHIFT |
437 yc->minC << ISPPRV_SETUP_YC_MINC_SHIFT |
438 yc->minY << ISPPRV_SETUP_YC_MINY_SHIFT,
439 OMAP3_ISP_IOMEM_PREV, ISPPRV_SETUP_YC);
440}
441
442
443
444
445static void
446preview_config_dcor(struct isp_prev_device *prev,
447 const struct prev_params *params)
448{
449 struct isp_device *isp = to_isp_device(prev);
450 const struct omap3isp_prev_dcor *dcor = ¶ms->dcor;
451
452 isp_reg_writel(isp, dcor->detect_correct[0],
453 OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR0);
454 isp_reg_writel(isp, dcor->detect_correct[1],
455 OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR1);
456 isp_reg_writel(isp, dcor->detect_correct[2],
457 OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR2);
458 isp_reg_writel(isp, dcor->detect_correct[3],
459 OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR3);
460 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
461 ISPPRV_PCR_DCCOUP,
462 dcor->couplet_mode_en ? ISPPRV_PCR_DCCOUP : 0);
463}
464
465
466
467
468static void preview_enable_dcor(struct isp_prev_device *prev, bool enable)
469{
470 struct isp_device *isp = to_isp_device(prev);
471
472 if (enable)
473 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
474 ISPPRV_PCR_DCOREN);
475 else
476 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
477 ISPPRV_PCR_DCOREN);
478}
479
480
481
482
483static void
484preview_enable_drkframe_capture(struct isp_prev_device *prev, bool enable)
485{
486 struct isp_device *isp = to_isp_device(prev);
487
488 if (enable)
489 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
490 ISPPRV_PCR_DRKFCAP);
491 else
492 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
493 ISPPRV_PCR_DRKFCAP);
494}
495
496
497
498
499static void preview_enable_drkframe(struct isp_prev_device *prev, bool enable)
500{
501 struct isp_device *isp = to_isp_device(prev);
502
503 if (enable)
504 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
505 ISPPRV_PCR_DRKFEN);
506 else
507 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
508 ISPPRV_PCR_DRKFEN);
509}
510
511
512
513
514static void
515preview_config_noisefilter(struct isp_prev_device *prev,
516 const struct prev_params *params)
517{
518 struct isp_device *isp = to_isp_device(prev);
519 const struct omap3isp_prev_nf *nf = ¶ms->nf;
520 unsigned int i;
521
522 isp_reg_writel(isp, nf->spread, OMAP3_ISP_IOMEM_PREV, ISPPRV_NF);
523 isp_reg_writel(isp, ISPPRV_NF_TABLE_ADDR,
524 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
525 for (i = 0; i < OMAP3ISP_PREV_NF_TBL_SIZE; i++) {
526 isp_reg_writel(isp, nf->table[i],
527 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
528 }
529}
530
531
532
533
534static void
535preview_enable_noisefilter(struct isp_prev_device *prev, bool enable)
536{
537 struct isp_device *isp = to_isp_device(prev);
538
539 if (enable)
540 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
541 ISPPRV_PCR_NFEN);
542 else
543 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
544 ISPPRV_PCR_NFEN);
545}
546
547
548
549
550static void
551preview_config_gammacorrn(struct isp_prev_device *prev,
552 const struct prev_params *params)
553{
554 struct isp_device *isp = to_isp_device(prev);
555 const struct omap3isp_prev_gtables *gt = ¶ms->gamma;
556 unsigned int i;
557
558 isp_reg_writel(isp, ISPPRV_REDGAMMA_TABLE_ADDR,
559 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
560 for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++)
561 isp_reg_writel(isp, gt->red[i], OMAP3_ISP_IOMEM_PREV,
562 ISPPRV_SET_TBL_DATA);
563
564 isp_reg_writel(isp, ISPPRV_GREENGAMMA_TABLE_ADDR,
565 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
566 for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++)
567 isp_reg_writel(isp, gt->green[i], OMAP3_ISP_IOMEM_PREV,
568 ISPPRV_SET_TBL_DATA);
569
570 isp_reg_writel(isp, ISPPRV_BLUEGAMMA_TABLE_ADDR,
571 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
572 for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++)
573 isp_reg_writel(isp, gt->blue[i], OMAP3_ISP_IOMEM_PREV,
574 ISPPRV_SET_TBL_DATA);
575}
576
577
578
579
580
581
582
583static void
584preview_enable_gammacorrn(struct isp_prev_device *prev, bool enable)
585{
586 struct isp_device *isp = to_isp_device(prev);
587
588 if (enable)
589 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
590 ISPPRV_PCR_GAMMA_BYPASS);
591 else
592 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
593 ISPPRV_PCR_GAMMA_BYPASS);
594}
595
596
597
598
599
600
601static void
602preview_config_contrast(struct isp_prev_device *prev,
603 const struct prev_params *params)
604{
605 struct isp_device *isp = to_isp_device(prev);
606
607 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT,
608 0xff << ISPPRV_CNT_BRT_CNT_SHIFT,
609 params->contrast << ISPPRV_CNT_BRT_CNT_SHIFT);
610}
611
612
613
614
615static void
616preview_config_brightness(struct isp_prev_device *prev,
617 const struct prev_params *params)
618{
619 struct isp_device *isp = to_isp_device(prev);
620
621 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT,
622 0xff << ISPPRV_CNT_BRT_BRT_SHIFT,
623 params->brightness << ISPPRV_CNT_BRT_BRT_SHIFT);
624}
625
626
627
628
629
630
631
632static void
633preview_update_contrast(struct isp_prev_device *prev, u8 contrast)
634{
635 struct prev_params *params;
636 unsigned long flags;
637
638 spin_lock_irqsave(&prev->params.lock, flags);
639 params = (prev->params.active & OMAP3ISP_PREV_CONTRAST)
640 ? &prev->params.params[0] : &prev->params.params[1];
641
642 if (params->contrast != (contrast * ISPPRV_CONTRAST_UNITS)) {
643 params->contrast = contrast * ISPPRV_CONTRAST_UNITS;
644 params->update |= OMAP3ISP_PREV_CONTRAST;
645 }
646 spin_unlock_irqrestore(&prev->params.lock, flags);
647}
648
649
650
651
652
653
654static void
655preview_update_brightness(struct isp_prev_device *prev, u8 brightness)
656{
657 struct prev_params *params;
658 unsigned long flags;
659
660 spin_lock_irqsave(&prev->params.lock, flags);
661 params = (prev->params.active & OMAP3ISP_PREV_BRIGHTNESS)
662 ? &prev->params.params[0] : &prev->params.params[1];
663
664 if (params->brightness != (brightness * ISPPRV_BRIGHT_UNITS)) {
665 params->brightness = brightness * ISPPRV_BRIGHT_UNITS;
666 params->update |= OMAP3ISP_PREV_BRIGHTNESS;
667 }
668 spin_unlock_irqrestore(&prev->params.lock, flags);
669}
670
671static u32
672preview_params_lock(struct isp_prev_device *prev, u32 update, bool shadow)
673{
674 u32 active = prev->params.active;
675
676 if (shadow) {
677
678 prev->params.params[0].busy |= ~active & update;
679 prev->params.params[1].busy |= active & update;
680 } else {
681
682 update = (prev->params.params[0].update & active)
683 | (prev->params.params[1].update & ~active);
684
685 prev->params.params[0].busy |= active & update;
686 prev->params.params[1].busy |= ~active & update;
687 }
688
689 return update;
690}
691
692static void
693preview_params_unlock(struct isp_prev_device *prev, u32 update, bool shadow)
694{
695 u32 active = prev->params.active;
696
697 if (shadow) {
698
699
700
701 prev->params.params[0].update |= (~active & update);
702 prev->params.params[1].update |= (active & update);
703 prev->params.params[0].busy &= active;
704 prev->params.params[1].busy &= ~active;
705 } else {
706
707
708
709 prev->params.params[0].update &= ~(active & update);
710 prev->params.params[1].update &= ~(~active & update);
711 prev->params.params[0].busy &= ~active;
712 prev->params.params[1].busy &= active;
713 }
714}
715
716static void preview_params_switch(struct isp_prev_device *prev)
717{
718 u32 to_switch;
719
720
721
722
723
724 to_switch = (prev->params.params[0].update & ~prev->params.active)
725 | (prev->params.params[1].update & prev->params.active);
726 to_switch &= ~(prev->params.params[0].busy |
727 prev->params.params[1].busy);
728 if (to_switch == 0)
729 return;
730
731 prev->params.active ^= to_switch;
732
733
734
735
736 prev->params.params[0].update &= ~(~prev->params.active & to_switch);
737 prev->params.params[1].update &= ~(prev->params.active & to_switch);
738}
739
740
741struct preview_update {
742 void (*config)(struct isp_prev_device *, const struct prev_params *);
743 void (*enable)(struct isp_prev_device *, bool);
744 unsigned int param_offset;
745 unsigned int param_size;
746 unsigned int config_offset;
747 bool skip;
748};
749
750
751static const struct preview_update update_attrs[] = {
752 {
753 preview_config_luma_enhancement,
754 preview_enable_luma_enhancement,
755 offsetof(struct prev_params, luma),
756 sizeof_field(struct prev_params, luma),
757 offsetof(struct omap3isp_prev_update_config, luma),
758 }, {
759 NULL,
760 preview_enable_invalaw,
761 }, {
762 preview_config_hmed,
763 preview_enable_hmed,
764 offsetof(struct prev_params, hmed),
765 sizeof_field(struct prev_params, hmed),
766 offsetof(struct omap3isp_prev_update_config, hmed),
767 }, {
768 preview_config_cfa,
769 NULL,
770 offsetof(struct prev_params, cfa),
771 sizeof_field(struct prev_params, cfa),
772 offsetof(struct omap3isp_prev_update_config, cfa),
773 }, {
774 preview_config_chroma_suppression,
775 preview_enable_chroma_suppression,
776 offsetof(struct prev_params, csup),
777 sizeof_field(struct prev_params, csup),
778 offsetof(struct omap3isp_prev_update_config, csup),
779 }, {
780 preview_config_whitebalance,
781 NULL,
782 offsetof(struct prev_params, wbal),
783 sizeof_field(struct prev_params, wbal),
784 offsetof(struct omap3isp_prev_update_config, wbal),
785 }, {
786 preview_config_blkadj,
787 NULL,
788 offsetof(struct prev_params, blkadj),
789 sizeof_field(struct prev_params, blkadj),
790 offsetof(struct omap3isp_prev_update_config, blkadj),
791 }, {
792 preview_config_rgb_blending,
793 NULL,
794 offsetof(struct prev_params, rgb2rgb),
795 sizeof_field(struct prev_params, rgb2rgb),
796 offsetof(struct omap3isp_prev_update_config, rgb2rgb),
797 }, {
798 preview_config_csc,
799 NULL,
800 offsetof(struct prev_params, csc),
801 sizeof_field(struct prev_params, csc),
802 offsetof(struct omap3isp_prev_update_config, csc),
803 }, {
804 preview_config_yc_range,
805 NULL,
806 offsetof(struct prev_params, yclimit),
807 sizeof_field(struct prev_params, yclimit),
808 offsetof(struct omap3isp_prev_update_config, yclimit),
809 }, {
810 preview_config_dcor,
811 preview_enable_dcor,
812 offsetof(struct prev_params, dcor),
813 sizeof_field(struct prev_params, dcor),
814 offsetof(struct omap3isp_prev_update_config, dcor),
815 }, {
816 NULL,
817 NULL,
818 }, {
819 NULL,
820 preview_enable_drkframe_capture,
821 }, {
822 NULL,
823 preview_enable_drkframe,
824 }, {
825 NULL,
826 preview_enable_drkframe,
827 }, {
828 preview_config_noisefilter,
829 preview_enable_noisefilter,
830 offsetof(struct prev_params, nf),
831 sizeof_field(struct prev_params, nf),
832 offsetof(struct omap3isp_prev_update_config, nf),
833 }, {
834 preview_config_gammacorrn,
835 preview_enable_gammacorrn,
836 offsetof(struct prev_params, gamma),
837 sizeof_field(struct prev_params, gamma),
838 offsetof(struct omap3isp_prev_update_config, gamma),
839 }, {
840 preview_config_contrast,
841 NULL,
842 0, 0, 0, true,
843 }, {
844 preview_config_brightness,
845 NULL,
846 0, 0, 0, true,
847 },
848};
849
850
851
852
853
854
855
856
857
858
859static int preview_config(struct isp_prev_device *prev,
860 struct omap3isp_prev_update_config *cfg)
861{
862 unsigned long flags;
863 unsigned int i;
864 int rval = 0;
865 u32 update;
866 u32 active;
867
868 if (cfg->update == 0)
869 return 0;
870
871
872 spin_lock_irqsave(&prev->params.lock, flags);
873 preview_params_lock(prev, cfg->update, true);
874 active = prev->params.active;
875 spin_unlock_irqrestore(&prev->params.lock, flags);
876
877 update = 0;
878
879 for (i = 0; i < ARRAY_SIZE(update_attrs); i++) {
880 const struct preview_update *attr = &update_attrs[i];
881 struct prev_params *params;
882 unsigned int bit = 1 << i;
883
884 if (attr->skip || !(cfg->update & bit))
885 continue;
886
887 params = &prev->params.params[!!(active & bit)];
888
889 if (cfg->flag & bit) {
890 void __user *from = *(void __user **)
891 ((void *)cfg + attr->config_offset);
892 void *to = (void *)params + attr->param_offset;
893 size_t size = attr->param_size;
894
895 if (to && from && size) {
896 if (copy_from_user(to, from, size)) {
897 rval = -EFAULT;
898 break;
899 }
900 }
901 params->features |= bit;
902 } else {
903 params->features &= ~bit;
904 }
905
906 update |= bit;
907 }
908
909 spin_lock_irqsave(&prev->params.lock, flags);
910 preview_params_unlock(prev, update, true);
911 preview_params_switch(prev);
912 spin_unlock_irqrestore(&prev->params.lock, flags);
913
914 return rval;
915}
916
917
918
919
920
921
922
923
924
925static void preview_setup_hw(struct isp_prev_device *prev, u32 update,
926 u32 active)
927{
928 unsigned int i;
929
930 if (update == 0)
931 return;
932
933 for (i = 0; i < ARRAY_SIZE(update_attrs); i++) {
934 const struct preview_update *attr = &update_attrs[i];
935 struct prev_params *params;
936 unsigned int bit = 1 << i;
937
938 if (!(update & bit))
939 continue;
940
941 params = &prev->params.params[!(active & bit)];
942
943 if (params->features & bit) {
944 if (attr->config)
945 attr->config(prev, params);
946 if (attr->enable)
947 attr->enable(prev, true);
948 } else {
949 if (attr->enable)
950 attr->enable(prev, false);
951 }
952 }
953}
954
955
956
957
958
959
960static void preview_config_ycpos(struct isp_prev_device *prev, u32 pixelcode)
961{
962 struct isp_device *isp = to_isp_device(prev);
963 enum preview_ycpos_mode mode;
964
965 switch (pixelcode) {
966 case MEDIA_BUS_FMT_YUYV8_1X16:
967 mode = YCPOS_CrYCbY;
968 break;
969 case MEDIA_BUS_FMT_UYVY8_1X16:
970 mode = YCPOS_YCrYCb;
971 break;
972 default:
973 return;
974 }
975
976 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
977 ISPPRV_PCR_YCPOS_CrYCbY,
978 mode << ISPPRV_PCR_YCPOS_SHIFT);
979}
980
981
982
983
984
985static void preview_config_averager(struct isp_prev_device *prev, u8 average)
986{
987 struct isp_device *isp = to_isp_device(prev);
988
989 isp_reg_writel(isp, ISPPRV_AVE_EVENDIST_2 << ISPPRV_AVE_EVENDIST_SHIFT |
990 ISPPRV_AVE_ODDDIST_2 << ISPPRV_AVE_ODDDIST_SHIFT |
991 average, OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE);
992}
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008static void preview_config_input_format(struct isp_prev_device *prev,
1009 const struct isp_format_info *info)
1010{
1011 struct isp_device *isp = to_isp_device(prev);
1012 struct prev_params *params;
1013
1014 if (info->width == 8)
1015 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1016 ISPPRV_PCR_WIDTH);
1017 else
1018 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1019 ISPPRV_PCR_WIDTH);
1020
1021 switch (info->flavor) {
1022 case MEDIA_BUS_FMT_SGRBG8_1X8:
1023 prev->params.cfa_order = 0;
1024 break;
1025 case MEDIA_BUS_FMT_SRGGB8_1X8:
1026 prev->params.cfa_order = 1;
1027 break;
1028 case MEDIA_BUS_FMT_SBGGR8_1X8:
1029 prev->params.cfa_order = 2;
1030 break;
1031 case MEDIA_BUS_FMT_SGBRG8_1X8:
1032 prev->params.cfa_order = 3;
1033 break;
1034 default:
1035
1036 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1037 ISPPRV_PCR_CFAEN);
1038 return;
1039 }
1040
1041 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_CFAEN);
1042 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1043 ISPPRV_PCR_CFAFMT_MASK, ISPPRV_PCR_CFAFMT_BAYER);
1044
1045 params = (prev->params.active & OMAP3ISP_PREV_CFA)
1046 ? &prev->params.params[0] : &prev->params.params[1];
1047
1048 preview_config_cfa(prev, params);
1049}
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062static void preview_config_input_size(struct isp_prev_device *prev, u32 active)
1063{
1064 const struct v4l2_mbus_framefmt *format = &prev->formats[PREV_PAD_SINK];
1065 struct isp_device *isp = to_isp_device(prev);
1066 unsigned int sph = prev->crop.left;
1067 unsigned int eph = prev->crop.left + prev->crop.width - 1;
1068 unsigned int slv = prev->crop.top;
1069 unsigned int elv = prev->crop.top + prev->crop.height - 1;
1070 u32 features;
1071
1072 if (format->code != MEDIA_BUS_FMT_Y8_1X8 &&
1073 format->code != MEDIA_BUS_FMT_Y10_1X10) {
1074 sph -= 2;
1075 eph += 2;
1076 slv -= 2;
1077 elv += 2;
1078 }
1079
1080 features = (prev->params.params[0].features & active)
1081 | (prev->params.params[1].features & ~active);
1082
1083 if (features & (OMAP3ISP_PREV_DEFECT_COR | OMAP3ISP_PREV_NF)) {
1084 sph -= 2;
1085 eph += 2;
1086 slv -= 2;
1087 elv += 2;
1088 }
1089 if (features & OMAP3ISP_PREV_HRZ_MED) {
1090 sph -= 2;
1091 eph += 2;
1092 }
1093 if (features & (OMAP3ISP_PREV_CHROMA_SUPP | OMAP3ISP_PREV_LUMAENH))
1094 sph -= 2;
1095
1096 isp_reg_writel(isp, (sph << ISPPRV_HORZ_INFO_SPH_SHIFT) | eph,
1097 OMAP3_ISP_IOMEM_PREV, ISPPRV_HORZ_INFO);
1098 isp_reg_writel(isp, (slv << ISPPRV_VERT_INFO_SLV_SHIFT) | elv,
1099 OMAP3_ISP_IOMEM_PREV, ISPPRV_VERT_INFO);
1100}
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112static void
1113preview_config_inlineoffset(struct isp_prev_device *prev, u32 offset)
1114{
1115 struct isp_device *isp = to_isp_device(prev);
1116
1117 isp_reg_writel(isp, offset & 0xffff, OMAP3_ISP_IOMEM_PREV,
1118 ISPPRV_RADR_OFFSET);
1119}
1120
1121
1122
1123
1124
1125
1126
1127static void preview_set_inaddr(struct isp_prev_device *prev, u32 addr)
1128{
1129 struct isp_device *isp = to_isp_device(prev);
1130
1131 isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_PREV, ISPPRV_RSDR_ADDR);
1132}
1133
1134
1135
1136
1137
1138
1139
1140static void preview_config_outlineoffset(struct isp_prev_device *prev,
1141 u32 offset)
1142{
1143 struct isp_device *isp = to_isp_device(prev);
1144
1145 isp_reg_writel(isp, offset & 0xffff, OMAP3_ISP_IOMEM_PREV,
1146 ISPPRV_WADD_OFFSET);
1147}
1148
1149
1150
1151
1152
1153
1154
1155static void preview_set_outaddr(struct isp_prev_device *prev, u32 addr)
1156{
1157 struct isp_device *isp = to_isp_device(prev);
1158
1159 isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_PREV, ISPPRV_WSDR_ADDR);
1160}
1161
1162static void preview_adjust_bandwidth(struct isp_prev_device *prev)
1163{
1164 struct isp_pipeline *pipe = to_isp_pipeline(&prev->subdev.entity);
1165 struct isp_device *isp = to_isp_device(prev);
1166 const struct v4l2_mbus_framefmt *ifmt = &prev->formats[PREV_PAD_SINK];
1167 unsigned long l3_ick = pipe->l3_ick;
1168 struct v4l2_fract *timeperframe;
1169 unsigned int cycles_per_frame;
1170 unsigned int requests_per_frame;
1171 unsigned int cycles_per_request;
1172 unsigned int minimum;
1173 unsigned int maximum;
1174 unsigned int value;
1175
1176 if (prev->input != PREVIEW_INPUT_MEMORY) {
1177 isp_reg_clr(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_SDR_REQ_EXP,
1178 ISPSBL_SDR_REQ_PRV_EXP_MASK);
1179 return;
1180 }
1181
1182
1183
1184
1185
1186 cycles_per_request = div_u64((u64)l3_ick / 2 * 256 + pipe->max_rate - 1,
1187 pipe->max_rate);
1188 minimum = DIV_ROUND_UP(cycles_per_request, 32);
1189
1190
1191
1192
1193
1194
1195 timeperframe = &pipe->max_timeperframe;
1196
1197 requests_per_frame = DIV_ROUND_UP(ifmt->width * 2, 256) * ifmt->height;
1198 cycles_per_frame = div_u64((u64)l3_ick * timeperframe->numerator,
1199 timeperframe->denominator);
1200 cycles_per_request = cycles_per_frame / requests_per_frame;
1201
1202 maximum = cycles_per_request / 32;
1203
1204 value = max(minimum, maximum);
1205
1206 dev_dbg(isp->dev, "%s: cycles per request = %u\n", __func__, value);
1207 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_SDR_REQ_EXP,
1208 ISPSBL_SDR_REQ_PRV_EXP_MASK,
1209 value << ISPSBL_SDR_REQ_PRV_EXP_SHIFT);
1210}
1211
1212
1213
1214
1215int omap3isp_preview_busy(struct isp_prev_device *prev)
1216{
1217 struct isp_device *isp = to_isp_device(prev);
1218
1219 return isp_reg_readl(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR)
1220 & ISPPRV_PCR_BUSY;
1221}
1222
1223
1224
1225
1226void omap3isp_preview_restore_context(struct isp_device *isp)
1227{
1228 struct isp_prev_device *prev = &isp->isp_prev;
1229 const u32 update = OMAP3ISP_PREV_FEATURES_END - 1;
1230
1231 prev->params.params[0].update = prev->params.active & update;
1232 prev->params.params[1].update = ~prev->params.active & update;
1233
1234 preview_setup_hw(prev, update, prev->params.active);
1235
1236 prev->params.params[0].update = 0;
1237 prev->params.params[1].update = 0;
1238}
1239
1240
1241
1242
1243#define PREV_PRINT_REGISTER(isp, name)\
1244 dev_dbg(isp->dev, "###PRV " #name "=0x%08x\n", \
1245 isp_reg_readl(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_##name))
1246
1247static void preview_print_status(struct isp_prev_device *prev)
1248{
1249 struct isp_device *isp = to_isp_device(prev);
1250
1251 dev_dbg(isp->dev, "-------------Preview Register dump----------\n");
1252
1253 PREV_PRINT_REGISTER(isp, PCR);
1254 PREV_PRINT_REGISTER(isp, HORZ_INFO);
1255 PREV_PRINT_REGISTER(isp, VERT_INFO);
1256 PREV_PRINT_REGISTER(isp, RSDR_ADDR);
1257 PREV_PRINT_REGISTER(isp, RADR_OFFSET);
1258 PREV_PRINT_REGISTER(isp, DSDR_ADDR);
1259 PREV_PRINT_REGISTER(isp, DRKF_OFFSET);
1260 PREV_PRINT_REGISTER(isp, WSDR_ADDR);
1261 PREV_PRINT_REGISTER(isp, WADD_OFFSET);
1262 PREV_PRINT_REGISTER(isp, AVE);
1263 PREV_PRINT_REGISTER(isp, HMED);
1264 PREV_PRINT_REGISTER(isp, NF);
1265 PREV_PRINT_REGISTER(isp, WB_DGAIN);
1266 PREV_PRINT_REGISTER(isp, WBGAIN);
1267 PREV_PRINT_REGISTER(isp, WBSEL);
1268 PREV_PRINT_REGISTER(isp, CFA);
1269 PREV_PRINT_REGISTER(isp, BLKADJOFF);
1270 PREV_PRINT_REGISTER(isp, RGB_MAT1);
1271 PREV_PRINT_REGISTER(isp, RGB_MAT2);
1272 PREV_PRINT_REGISTER(isp, RGB_MAT3);
1273 PREV_PRINT_REGISTER(isp, RGB_MAT4);
1274 PREV_PRINT_REGISTER(isp, RGB_MAT5);
1275 PREV_PRINT_REGISTER(isp, RGB_OFF1);
1276 PREV_PRINT_REGISTER(isp, RGB_OFF2);
1277 PREV_PRINT_REGISTER(isp, CSC0);
1278 PREV_PRINT_REGISTER(isp, CSC1);
1279 PREV_PRINT_REGISTER(isp, CSC2);
1280 PREV_PRINT_REGISTER(isp, CSC_OFFSET);
1281 PREV_PRINT_REGISTER(isp, CNT_BRT);
1282 PREV_PRINT_REGISTER(isp, CSUP);
1283 PREV_PRINT_REGISTER(isp, SETUP_YC);
1284 PREV_PRINT_REGISTER(isp, SET_TBL_ADDR);
1285 PREV_PRINT_REGISTER(isp, CDC_THR0);
1286 PREV_PRINT_REGISTER(isp, CDC_THR1);
1287 PREV_PRINT_REGISTER(isp, CDC_THR2);
1288 PREV_PRINT_REGISTER(isp, CDC_THR3);
1289
1290 dev_dbg(isp->dev, "--------------------------------------------\n");
1291}
1292
1293
1294
1295
1296
1297static void preview_init_params(struct isp_prev_device *prev)
1298{
1299 struct prev_params *params;
1300 unsigned int i;
1301
1302 spin_lock_init(&prev->params.lock);
1303
1304 prev->params.active = ~0;
1305 prev->params.params[0].busy = 0;
1306 prev->params.params[0].update = OMAP3ISP_PREV_FEATURES_END - 1;
1307 prev->params.params[1].busy = 0;
1308 prev->params.params[1].update = 0;
1309
1310 params = &prev->params.params[0];
1311
1312
1313 params->contrast = ISPPRV_CONTRAST_DEF * ISPPRV_CONTRAST_UNITS;
1314 params->brightness = ISPPRV_BRIGHT_DEF * ISPPRV_BRIGHT_UNITS;
1315 params->cfa.format = OMAP3ISP_CFAFMT_BAYER;
1316 memcpy(params->cfa.table, cfa_coef_table,
1317 sizeof(params->cfa.table));
1318 params->cfa.gradthrs_horz = FLR_CFA_GRADTHRS_HORZ;
1319 params->cfa.gradthrs_vert = FLR_CFA_GRADTHRS_VERT;
1320 params->csup.gain = FLR_CSUP_GAIN;
1321 params->csup.thres = FLR_CSUP_THRES;
1322 params->csup.hypf_en = 0;
1323 memcpy(params->luma.table, luma_enhance_table,
1324 sizeof(params->luma.table));
1325 params->nf.spread = FLR_NF_STRGTH;
1326 memcpy(params->nf.table, noise_filter_table, sizeof(params->nf.table));
1327 params->dcor.couplet_mode_en = 1;
1328 for (i = 0; i < OMAP3ISP_PREV_DETECT_CORRECT_CHANNELS; i++)
1329 params->dcor.detect_correct[i] = DEF_DETECT_CORRECT_VAL;
1330 memcpy(params->gamma.blue, gamma_table, sizeof(params->gamma.blue));
1331 memcpy(params->gamma.green, gamma_table, sizeof(params->gamma.green));
1332 memcpy(params->gamma.red, gamma_table, sizeof(params->gamma.red));
1333 params->wbal.dgain = FLR_WBAL_DGAIN;
1334 params->wbal.coef0 = FLR_WBAL_COEF;
1335 params->wbal.coef1 = FLR_WBAL_COEF;
1336 params->wbal.coef2 = FLR_WBAL_COEF;
1337 params->wbal.coef3 = FLR_WBAL_COEF;
1338 params->blkadj.red = FLR_BLKADJ_RED;
1339 params->blkadj.green = FLR_BLKADJ_GREEN;
1340 params->blkadj.blue = FLR_BLKADJ_BLUE;
1341 params->rgb2rgb = flr_rgb2rgb;
1342 params->csc = flr_prev_csc;
1343 params->yclimit.minC = ISPPRV_YC_MIN;
1344 params->yclimit.maxC = ISPPRV_YC_MAX;
1345 params->yclimit.minY = ISPPRV_YC_MIN;
1346 params->yclimit.maxY = ISPPRV_YC_MAX;
1347
1348 params->features = OMAP3ISP_PREV_CFA | OMAP3ISP_PREV_DEFECT_COR
1349 | OMAP3ISP_PREV_NF | OMAP3ISP_PREV_GAMMA
1350 | OMAP3ISP_PREV_BLKADJ | OMAP3ISP_PREV_YC_LIMIT
1351 | OMAP3ISP_PREV_RGB2RGB | OMAP3ISP_PREV_COLOR_CONV
1352 | OMAP3ISP_PREV_WB | OMAP3ISP_PREV_BRIGHTNESS
1353 | OMAP3ISP_PREV_CONTRAST;
1354}
1355
1356
1357
1358
1359
1360
1361static unsigned int preview_max_out_width(struct isp_prev_device *prev)
1362{
1363 struct isp_device *isp = to_isp_device(prev);
1364
1365 switch (isp->revision) {
1366 case ISP_REVISION_1_0:
1367 return PREV_MAX_OUT_WIDTH_REV_1;
1368
1369 case ISP_REVISION_2_0:
1370 default:
1371 return PREV_MAX_OUT_WIDTH_REV_2;
1372
1373 case ISP_REVISION_15_0:
1374 return PREV_MAX_OUT_WIDTH_REV_15;
1375 }
1376}
1377
1378static void preview_configure(struct isp_prev_device *prev)
1379{
1380 struct isp_device *isp = to_isp_device(prev);
1381 const struct isp_format_info *info;
1382 struct v4l2_mbus_framefmt *format;
1383 unsigned long flags;
1384 u32 update;
1385 u32 active;
1386
1387 spin_lock_irqsave(&prev->params.lock, flags);
1388
1389 update = preview_params_lock(prev, 0, false);
1390 active = prev->params.active;
1391 spin_unlock_irqrestore(&prev->params.lock, flags);
1392
1393
1394 format = &prev->formats[PREV_PAD_SINK];
1395 info = omap3isp_video_format_info(format->code);
1396
1397 preview_adjust_bandwidth(prev);
1398
1399 preview_config_input_format(prev, info);
1400 preview_config_input_size(prev, active);
1401
1402 if (prev->input == PREVIEW_INPUT_CCDC)
1403 preview_config_inlineoffset(prev, 0);
1404 else
1405 preview_config_inlineoffset(prev, ALIGN(format->width, 0x20) *
1406 info->bpp);
1407
1408 preview_setup_hw(prev, update, active);
1409
1410
1411 format = &prev->formats[PREV_PAD_SOURCE];
1412
1413 if (prev->output & PREVIEW_OUTPUT_MEMORY)
1414 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1415 ISPPRV_PCR_SDRPORT);
1416 else
1417 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1418 ISPPRV_PCR_SDRPORT);
1419
1420 if (prev->output & PREVIEW_OUTPUT_RESIZER)
1421 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1422 ISPPRV_PCR_RSZPORT);
1423 else
1424 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1425 ISPPRV_PCR_RSZPORT);
1426
1427 if (prev->output & PREVIEW_OUTPUT_MEMORY)
1428 preview_config_outlineoffset(prev,
1429 ALIGN(format->width, 0x10) * 2);
1430
1431 preview_config_averager(prev, 0);
1432 preview_config_ycpos(prev, format->code);
1433
1434 spin_lock_irqsave(&prev->params.lock, flags);
1435 preview_params_unlock(prev, update, false);
1436 spin_unlock_irqrestore(&prev->params.lock, flags);
1437}
1438
1439
1440
1441
1442
1443static void preview_enable_oneshot(struct isp_prev_device *prev)
1444{
1445 struct isp_device *isp = to_isp_device(prev);
1446
1447
1448
1449
1450
1451 if (prev->input == PREVIEW_INPUT_MEMORY)
1452 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1453 ISPPRV_PCR_SOURCE);
1454
1455 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1456 ISPPRV_PCR_EN | ISPPRV_PCR_ONESHOT);
1457}
1458
1459void omap3isp_preview_isr_frame_sync(struct isp_prev_device *prev)
1460{
1461
1462
1463
1464
1465
1466
1467 if (prev->state == ISP_PIPELINE_STREAM_CONTINUOUS &&
1468 prev->video_out.dmaqueue_flags & ISP_VIDEO_DMAQUEUE_QUEUED) {
1469 preview_enable_oneshot(prev);
1470 isp_video_dmaqueue_flags_clr(&prev->video_out);
1471 }
1472}
1473
1474static void preview_isr_buffer(struct isp_prev_device *prev)
1475{
1476 struct isp_pipeline *pipe = to_isp_pipeline(&prev->subdev.entity);
1477 struct isp_buffer *buffer;
1478 int restart = 0;
1479
1480 if (prev->output & PREVIEW_OUTPUT_MEMORY) {
1481 buffer = omap3isp_video_buffer_next(&prev->video_out);
1482 if (buffer != NULL) {
1483 preview_set_outaddr(prev, buffer->dma);
1484 restart = 1;
1485 }
1486 pipe->state |= ISP_PIPELINE_IDLE_OUTPUT;
1487 }
1488
1489 if (prev->input == PREVIEW_INPUT_MEMORY) {
1490 buffer = omap3isp_video_buffer_next(&prev->video_in);
1491 if (buffer != NULL)
1492 preview_set_inaddr(prev, buffer->dma);
1493 pipe->state |= ISP_PIPELINE_IDLE_INPUT;
1494 }
1495
1496 switch (prev->state) {
1497 case ISP_PIPELINE_STREAM_SINGLESHOT:
1498 if (isp_pipeline_ready(pipe))
1499 omap3isp_pipeline_set_stream(pipe,
1500 ISP_PIPELINE_STREAM_SINGLESHOT);
1501 break;
1502
1503 case ISP_PIPELINE_STREAM_CONTINUOUS:
1504
1505
1506
1507 if (restart)
1508 preview_enable_oneshot(prev);
1509 break;
1510
1511 case ISP_PIPELINE_STREAM_STOPPED:
1512 default:
1513 return;
1514 }
1515}
1516
1517
1518
1519
1520
1521
1522void omap3isp_preview_isr(struct isp_prev_device *prev)
1523{
1524 unsigned long flags;
1525 u32 update;
1526 u32 active;
1527
1528 if (omap3isp_module_sync_is_stopping(&prev->wait, &prev->stopping))
1529 return;
1530
1531 spin_lock_irqsave(&prev->params.lock, flags);
1532 preview_params_switch(prev);
1533 update = preview_params_lock(prev, 0, false);
1534 active = prev->params.active;
1535 spin_unlock_irqrestore(&prev->params.lock, flags);
1536
1537 preview_setup_hw(prev, update, active);
1538 preview_config_input_size(prev, active);
1539
1540 if (prev->input == PREVIEW_INPUT_MEMORY ||
1541 prev->output & PREVIEW_OUTPUT_MEMORY)
1542 preview_isr_buffer(prev);
1543 else if (prev->state == ISP_PIPELINE_STREAM_CONTINUOUS)
1544 preview_enable_oneshot(prev);
1545
1546 spin_lock_irqsave(&prev->params.lock, flags);
1547 preview_params_unlock(prev, update, false);
1548 spin_unlock_irqrestore(&prev->params.lock, flags);
1549}
1550
1551
1552
1553
1554
1555static int preview_video_queue(struct isp_video *video,
1556 struct isp_buffer *buffer)
1557{
1558 struct isp_prev_device *prev = &video->isp->isp_prev;
1559
1560 if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
1561 preview_set_inaddr(prev, buffer->dma);
1562
1563 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1564 preview_set_outaddr(prev, buffer->dma);
1565
1566 return 0;
1567}
1568
1569static const struct isp_video_operations preview_video_ops = {
1570 .queue = preview_video_queue,
1571};
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581static int preview_s_ctrl(struct v4l2_ctrl *ctrl)
1582{
1583 struct isp_prev_device *prev =
1584 container_of(ctrl->handler, struct isp_prev_device, ctrls);
1585
1586 switch (ctrl->id) {
1587 case V4L2_CID_BRIGHTNESS:
1588 preview_update_brightness(prev, ctrl->val);
1589 break;
1590 case V4L2_CID_CONTRAST:
1591 preview_update_contrast(prev, ctrl->val);
1592 break;
1593 }
1594
1595 return 0;
1596}
1597
1598static const struct v4l2_ctrl_ops preview_ctrl_ops = {
1599 .s_ctrl = preview_s_ctrl,
1600};
1601
1602
1603
1604
1605
1606
1607
1608
1609static long preview_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
1610{
1611 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1612
1613 switch (cmd) {
1614 case VIDIOC_OMAP3ISP_PRV_CFG:
1615 return preview_config(prev, arg);
1616
1617 default:
1618 return -ENOIOCTLCMD;
1619 }
1620}
1621
1622
1623
1624
1625
1626
1627
1628static int preview_set_stream(struct v4l2_subdev *sd, int enable)
1629{
1630 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1631 struct isp_video *video_out = &prev->video_out;
1632 struct isp_device *isp = to_isp_device(prev);
1633 struct device *dev = to_device(prev);
1634
1635 if (prev->state == ISP_PIPELINE_STREAM_STOPPED) {
1636 if (enable == ISP_PIPELINE_STREAM_STOPPED)
1637 return 0;
1638
1639 omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_PREVIEW);
1640 preview_configure(prev);
1641 atomic_set(&prev->stopping, 0);
1642 preview_print_status(prev);
1643 }
1644
1645 switch (enable) {
1646 case ISP_PIPELINE_STREAM_CONTINUOUS:
1647 if (prev->output & PREVIEW_OUTPUT_MEMORY)
1648 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_PREVIEW_WRITE);
1649
1650 if (video_out->dmaqueue_flags & ISP_VIDEO_DMAQUEUE_QUEUED ||
1651 !(prev->output & PREVIEW_OUTPUT_MEMORY))
1652 preview_enable_oneshot(prev);
1653
1654 isp_video_dmaqueue_flags_clr(video_out);
1655 break;
1656
1657 case ISP_PIPELINE_STREAM_SINGLESHOT:
1658 if (prev->input == PREVIEW_INPUT_MEMORY)
1659 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_PREVIEW_READ);
1660 if (prev->output & PREVIEW_OUTPUT_MEMORY)
1661 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_PREVIEW_WRITE);
1662
1663 preview_enable_oneshot(prev);
1664 break;
1665
1666 case ISP_PIPELINE_STREAM_STOPPED:
1667 if (omap3isp_module_sync_idle(&sd->entity, &prev->wait,
1668 &prev->stopping))
1669 dev_dbg(dev, "%s: stop timeout.\n", sd->name);
1670 omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_PREVIEW_READ);
1671 omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_PREVIEW_WRITE);
1672 omap3isp_subclk_disable(isp, OMAP3_ISP_SUBCLK_PREVIEW);
1673 isp_video_dmaqueue_flags_clr(video_out);
1674 break;
1675 }
1676
1677 prev->state = enable;
1678 return 0;
1679}
1680
1681static struct v4l2_mbus_framefmt *
1682__preview_get_format(struct isp_prev_device *prev, struct v4l2_subdev_pad_config *cfg,
1683 unsigned int pad, enum v4l2_subdev_format_whence which)
1684{
1685 if (which == V4L2_SUBDEV_FORMAT_TRY)
1686 return v4l2_subdev_get_try_format(&prev->subdev, cfg, pad);
1687 else
1688 return &prev->formats[pad];
1689}
1690
1691static struct v4l2_rect *
1692__preview_get_crop(struct isp_prev_device *prev, struct v4l2_subdev_pad_config *cfg,
1693 enum v4l2_subdev_format_whence which)
1694{
1695 if (which == V4L2_SUBDEV_FORMAT_TRY)
1696 return v4l2_subdev_get_try_crop(&prev->subdev, cfg, PREV_PAD_SINK);
1697 else
1698 return &prev->crop;
1699}
1700
1701
1702static const unsigned int preview_input_fmts[] = {
1703 MEDIA_BUS_FMT_Y8_1X8,
1704 MEDIA_BUS_FMT_SGRBG8_1X8,
1705 MEDIA_BUS_FMT_SRGGB8_1X8,
1706 MEDIA_BUS_FMT_SBGGR8_1X8,
1707 MEDIA_BUS_FMT_SGBRG8_1X8,
1708 MEDIA_BUS_FMT_Y10_1X10,
1709 MEDIA_BUS_FMT_SGRBG10_1X10,
1710 MEDIA_BUS_FMT_SRGGB10_1X10,
1711 MEDIA_BUS_FMT_SBGGR10_1X10,
1712 MEDIA_BUS_FMT_SGBRG10_1X10,
1713};
1714
1715static const unsigned int preview_output_fmts[] = {
1716 MEDIA_BUS_FMT_UYVY8_1X16,
1717 MEDIA_BUS_FMT_YUYV8_1X16,
1718};
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731static void preview_try_format(struct isp_prev_device *prev,
1732 struct v4l2_subdev_pad_config *cfg, unsigned int pad,
1733 struct v4l2_mbus_framefmt *fmt,
1734 enum v4l2_subdev_format_whence which)
1735{
1736 u32 pixelcode;
1737 struct v4l2_rect *crop;
1738 unsigned int i;
1739
1740 switch (pad) {
1741 case PREV_PAD_SINK:
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751 if (prev->input == PREVIEW_INPUT_MEMORY) {
1752 fmt->width = clamp_t(u32, fmt->width, PREV_MIN_IN_WIDTH,
1753 preview_max_out_width(prev));
1754 fmt->height = clamp_t(u32, fmt->height,
1755 PREV_MIN_IN_HEIGHT,
1756 PREV_MAX_IN_HEIGHT);
1757 }
1758
1759 fmt->colorspace = V4L2_COLORSPACE_SRGB;
1760
1761 for (i = 0; i < ARRAY_SIZE(preview_input_fmts); i++) {
1762 if (fmt->code == preview_input_fmts[i])
1763 break;
1764 }
1765
1766
1767 if (i >= ARRAY_SIZE(preview_input_fmts))
1768 fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
1769 break;
1770
1771 case PREV_PAD_SOURCE:
1772 pixelcode = fmt->code;
1773 *fmt = *__preview_get_format(prev, cfg, PREV_PAD_SINK, which);
1774
1775 switch (pixelcode) {
1776 case MEDIA_BUS_FMT_YUYV8_1X16:
1777 case MEDIA_BUS_FMT_UYVY8_1X16:
1778 fmt->code = pixelcode;
1779 break;
1780
1781 default:
1782 fmt->code = MEDIA_BUS_FMT_YUYV8_1X16;
1783 break;
1784 }
1785
1786
1787
1788
1789
1790
1791 crop = __preview_get_crop(prev, cfg, which);
1792 fmt->width = crop->width;
1793 fmt->height = crop->height;
1794
1795 fmt->colorspace = V4L2_COLORSPACE_JPEG;
1796 break;
1797 }
1798
1799 fmt->field = V4L2_FIELD_NONE;
1800}
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814static void preview_try_crop(struct isp_prev_device *prev,
1815 const struct v4l2_mbus_framefmt *sink,
1816 struct v4l2_rect *crop)
1817{
1818 unsigned int left = PREV_MARGIN_LEFT;
1819 unsigned int right = sink->width - PREV_MARGIN_RIGHT;
1820 unsigned int top = PREV_MARGIN_TOP;
1821 unsigned int bottom = sink->height - PREV_MARGIN_BOTTOM;
1822
1823
1824
1825
1826
1827
1828 if (prev->input == PREVIEW_INPUT_CCDC) {
1829 left += 2;
1830 right -= 2;
1831 }
1832
1833
1834
1835
1836
1837 if (sink->code != MEDIA_BUS_FMT_Y8_1X8 &&
1838 sink->code != MEDIA_BUS_FMT_Y10_1X10) {
1839 left += 2;
1840 right -= 2;
1841 top += 2;
1842 bottom -= 2;
1843 }
1844
1845
1846 crop->left &= ~1;
1847 crop->top &= ~1;
1848
1849 crop->left = clamp_t(u32, crop->left, left, right - PREV_MIN_OUT_WIDTH);
1850 crop->top = clamp_t(u32, crop->top, top, bottom - PREV_MIN_OUT_HEIGHT);
1851 crop->width = clamp_t(u32, crop->width, PREV_MIN_OUT_WIDTH,
1852 right - crop->left);
1853 crop->height = clamp_t(u32, crop->height, PREV_MIN_OUT_HEIGHT,
1854 bottom - crop->top);
1855}
1856
1857
1858
1859
1860
1861
1862
1863
1864static int preview_enum_mbus_code(struct v4l2_subdev *sd,
1865 struct v4l2_subdev_pad_config *cfg,
1866 struct v4l2_subdev_mbus_code_enum *code)
1867{
1868 switch (code->pad) {
1869 case PREV_PAD_SINK:
1870 if (code->index >= ARRAY_SIZE(preview_input_fmts))
1871 return -EINVAL;
1872
1873 code->code = preview_input_fmts[code->index];
1874 break;
1875 case PREV_PAD_SOURCE:
1876 if (code->index >= ARRAY_SIZE(preview_output_fmts))
1877 return -EINVAL;
1878
1879 code->code = preview_output_fmts[code->index];
1880 break;
1881 default:
1882 return -EINVAL;
1883 }
1884
1885 return 0;
1886}
1887
1888static int preview_enum_frame_size(struct v4l2_subdev *sd,
1889 struct v4l2_subdev_pad_config *cfg,
1890 struct v4l2_subdev_frame_size_enum *fse)
1891{
1892 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1893 struct v4l2_mbus_framefmt format;
1894
1895 if (fse->index != 0)
1896 return -EINVAL;
1897
1898 format.code = fse->code;
1899 format.width = 1;
1900 format.height = 1;
1901 preview_try_format(prev, cfg, fse->pad, &format, fse->which);
1902 fse->min_width = format.width;
1903 fse->min_height = format.height;
1904
1905 if (format.code != fse->code)
1906 return -EINVAL;
1907
1908 format.code = fse->code;
1909 format.width = -1;
1910 format.height = -1;
1911 preview_try_format(prev, cfg, fse->pad, &format, fse->which);
1912 fse->max_width = format.width;
1913 fse->max_height = format.height;
1914
1915 return 0;
1916}
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928static int preview_get_selection(struct v4l2_subdev *sd,
1929 struct v4l2_subdev_pad_config *cfg,
1930 struct v4l2_subdev_selection *sel)
1931{
1932 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1933 struct v4l2_mbus_framefmt *format;
1934
1935 if (sel->pad != PREV_PAD_SINK)
1936 return -EINVAL;
1937
1938 switch (sel->target) {
1939 case V4L2_SEL_TGT_CROP_BOUNDS:
1940 sel->r.left = 0;
1941 sel->r.top = 0;
1942 sel->r.width = INT_MAX;
1943 sel->r.height = INT_MAX;
1944
1945 format = __preview_get_format(prev, cfg, PREV_PAD_SINK,
1946 sel->which);
1947 preview_try_crop(prev, format, &sel->r);
1948 break;
1949
1950 case V4L2_SEL_TGT_CROP:
1951 sel->r = *__preview_get_crop(prev, cfg, sel->which);
1952 break;
1953
1954 default:
1955 return -EINVAL;
1956 }
1957
1958 return 0;
1959}
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971static int preview_set_selection(struct v4l2_subdev *sd,
1972 struct v4l2_subdev_pad_config *cfg,
1973 struct v4l2_subdev_selection *sel)
1974{
1975 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1976 struct v4l2_mbus_framefmt *format;
1977
1978 if (sel->target != V4L2_SEL_TGT_CROP ||
1979 sel->pad != PREV_PAD_SINK)
1980 return -EINVAL;
1981
1982
1983 if (prev->state != ISP_PIPELINE_STREAM_STOPPED)
1984 return -EBUSY;
1985
1986
1987
1988
1989
1990 if (sel->flags & V4L2_SEL_FLAG_KEEP_CONFIG) {
1991 sel->r = *__preview_get_crop(prev, cfg, sel->which);
1992 return 0;
1993 }
1994
1995 format = __preview_get_format(prev, cfg, PREV_PAD_SINK, sel->which);
1996 preview_try_crop(prev, format, &sel->r);
1997 *__preview_get_crop(prev, cfg, sel->which) = sel->r;
1998
1999
2000 format = __preview_get_format(prev, cfg, PREV_PAD_SOURCE, sel->which);
2001 preview_try_format(prev, cfg, PREV_PAD_SOURCE, format, sel->which);
2002
2003 return 0;
2004}
2005
2006
2007
2008
2009
2010
2011
2012
2013static int preview_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
2014 struct v4l2_subdev_format *fmt)
2015{
2016 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
2017 struct v4l2_mbus_framefmt *format;
2018
2019 format = __preview_get_format(prev, cfg, fmt->pad, fmt->which);
2020 if (format == NULL)
2021 return -EINVAL;
2022
2023 fmt->format = *format;
2024 return 0;
2025}
2026
2027
2028
2029
2030
2031
2032
2033
2034static int preview_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
2035 struct v4l2_subdev_format *fmt)
2036{
2037 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
2038 struct v4l2_mbus_framefmt *format;
2039 struct v4l2_rect *crop;
2040
2041 format = __preview_get_format(prev, cfg, fmt->pad, fmt->which);
2042 if (format == NULL)
2043 return -EINVAL;
2044
2045 preview_try_format(prev, cfg, fmt->pad, &fmt->format, fmt->which);
2046 *format = fmt->format;
2047
2048
2049 if (fmt->pad == PREV_PAD_SINK) {
2050
2051 crop = __preview_get_crop(prev, cfg, fmt->which);
2052 crop->left = 0;
2053 crop->top = 0;
2054 crop->width = fmt->format.width;
2055 crop->height = fmt->format.height;
2056
2057 preview_try_crop(prev, &fmt->format, crop);
2058
2059
2060 format = __preview_get_format(prev, cfg, PREV_PAD_SOURCE,
2061 fmt->which);
2062 preview_try_format(prev, cfg, PREV_PAD_SOURCE, format,
2063 fmt->which);
2064 }
2065
2066 return 0;
2067}
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078static int preview_init_formats(struct v4l2_subdev *sd,
2079 struct v4l2_subdev_fh *fh)
2080{
2081 struct v4l2_subdev_format format;
2082
2083 memset(&format, 0, sizeof(format));
2084 format.pad = PREV_PAD_SINK;
2085 format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
2086 format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
2087 format.format.width = 4096;
2088 format.format.height = 4096;
2089 preview_set_format(sd, fh ? fh->pad : NULL, &format);
2090
2091 return 0;
2092}
2093
2094
2095static const struct v4l2_subdev_core_ops preview_v4l2_core_ops = {
2096 .ioctl = preview_ioctl,
2097};
2098
2099
2100static const struct v4l2_subdev_video_ops preview_v4l2_video_ops = {
2101 .s_stream = preview_set_stream,
2102};
2103
2104
2105static const struct v4l2_subdev_pad_ops preview_v4l2_pad_ops = {
2106 .enum_mbus_code = preview_enum_mbus_code,
2107 .enum_frame_size = preview_enum_frame_size,
2108 .get_fmt = preview_get_format,
2109 .set_fmt = preview_set_format,
2110 .get_selection = preview_get_selection,
2111 .set_selection = preview_set_selection,
2112};
2113
2114
2115static const struct v4l2_subdev_ops preview_v4l2_ops = {
2116 .core = &preview_v4l2_core_ops,
2117 .video = &preview_v4l2_video_ops,
2118 .pad = &preview_v4l2_pad_ops,
2119};
2120
2121
2122static const struct v4l2_subdev_internal_ops preview_v4l2_internal_ops = {
2123 .open = preview_init_formats,
2124};
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138static int preview_link_setup(struct media_entity *entity,
2139 const struct media_pad *local,
2140 const struct media_pad *remote, u32 flags)
2141{
2142 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
2143 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
2144 unsigned int index = local->index;
2145
2146
2147 if (is_media_entity_v4l2_subdev(remote->entity))
2148 index |= 2 << 16;
2149
2150 switch (index) {
2151 case PREV_PAD_SINK:
2152
2153 if (flags & MEDIA_LNK_FL_ENABLED) {
2154 if (prev->input == PREVIEW_INPUT_CCDC)
2155 return -EBUSY;
2156 prev->input = PREVIEW_INPUT_MEMORY;
2157 } else {
2158 if (prev->input == PREVIEW_INPUT_MEMORY)
2159 prev->input = PREVIEW_INPUT_NONE;
2160 }
2161 break;
2162
2163 case PREV_PAD_SINK | 2 << 16:
2164
2165 if (flags & MEDIA_LNK_FL_ENABLED) {
2166 if (prev->input == PREVIEW_INPUT_MEMORY)
2167 return -EBUSY;
2168 prev->input = PREVIEW_INPUT_CCDC;
2169 } else {
2170 if (prev->input == PREVIEW_INPUT_CCDC)
2171 prev->input = PREVIEW_INPUT_NONE;
2172 }
2173 break;
2174
2175
2176
2177
2178
2179
2180 case PREV_PAD_SOURCE:
2181
2182 if (flags & MEDIA_LNK_FL_ENABLED) {
2183 if (prev->output & ~PREVIEW_OUTPUT_MEMORY)
2184 return -EBUSY;
2185 prev->output |= PREVIEW_OUTPUT_MEMORY;
2186 } else {
2187 prev->output &= ~PREVIEW_OUTPUT_MEMORY;
2188 }
2189 break;
2190
2191 case PREV_PAD_SOURCE | 2 << 16:
2192
2193 if (flags & MEDIA_LNK_FL_ENABLED) {
2194 if (prev->output & ~PREVIEW_OUTPUT_RESIZER)
2195 return -EBUSY;
2196 prev->output |= PREVIEW_OUTPUT_RESIZER;
2197 } else {
2198 prev->output &= ~PREVIEW_OUTPUT_RESIZER;
2199 }
2200 break;
2201
2202 default:
2203 return -EINVAL;
2204 }
2205
2206 return 0;
2207}
2208
2209
2210static const struct media_entity_operations preview_media_ops = {
2211 .link_setup = preview_link_setup,
2212 .link_validate = v4l2_subdev_link_validate,
2213};
2214
2215void omap3isp_preview_unregister_entities(struct isp_prev_device *prev)
2216{
2217 v4l2_device_unregister_subdev(&prev->subdev);
2218 omap3isp_video_unregister(&prev->video_in);
2219 omap3isp_video_unregister(&prev->video_out);
2220}
2221
2222int omap3isp_preview_register_entities(struct isp_prev_device *prev,
2223 struct v4l2_device *vdev)
2224{
2225 int ret;
2226
2227
2228 prev->subdev.dev = vdev->mdev->dev;
2229 ret = v4l2_device_register_subdev(vdev, &prev->subdev);
2230 if (ret < 0)
2231 goto error;
2232
2233 ret = omap3isp_video_register(&prev->video_in, vdev);
2234 if (ret < 0)
2235 goto error;
2236
2237 ret = omap3isp_video_register(&prev->video_out, vdev);
2238 if (ret < 0)
2239 goto error;
2240
2241 return 0;
2242
2243error:
2244 omap3isp_preview_unregister_entities(prev);
2245 return ret;
2246}
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257static int preview_init_entities(struct isp_prev_device *prev)
2258{
2259 struct v4l2_subdev *sd = &prev->subdev;
2260 struct media_pad *pads = prev->pads;
2261 struct media_entity *me = &sd->entity;
2262 int ret;
2263
2264 prev->input = PREVIEW_INPUT_NONE;
2265
2266 v4l2_subdev_init(sd, &preview_v4l2_ops);
2267 sd->internal_ops = &preview_v4l2_internal_ops;
2268 strscpy(sd->name, "OMAP3 ISP preview", sizeof(sd->name));
2269 sd->grp_id = 1 << 16;
2270 v4l2_set_subdevdata(sd, prev);
2271 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
2272
2273 v4l2_ctrl_handler_init(&prev->ctrls, 2);
2274 v4l2_ctrl_new_std(&prev->ctrls, &preview_ctrl_ops, V4L2_CID_BRIGHTNESS,
2275 ISPPRV_BRIGHT_LOW, ISPPRV_BRIGHT_HIGH,
2276 ISPPRV_BRIGHT_STEP, ISPPRV_BRIGHT_DEF);
2277 v4l2_ctrl_new_std(&prev->ctrls, &preview_ctrl_ops, V4L2_CID_CONTRAST,
2278 ISPPRV_CONTRAST_LOW, ISPPRV_CONTRAST_HIGH,
2279 ISPPRV_CONTRAST_STEP, ISPPRV_CONTRAST_DEF);
2280 v4l2_ctrl_handler_setup(&prev->ctrls);
2281 sd->ctrl_handler = &prev->ctrls;
2282
2283 pads[PREV_PAD_SINK].flags = MEDIA_PAD_FL_SINK
2284 | MEDIA_PAD_FL_MUST_CONNECT;
2285 pads[PREV_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
2286
2287 me->ops = &preview_media_ops;
2288 ret = media_entity_pads_init(me, PREV_PADS_NUM, pads);
2289 if (ret < 0)
2290 goto error_handler_free;
2291
2292 preview_init_formats(sd, NULL);
2293
2294
2295
2296
2297
2298 prev->video_in.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
2299 prev->video_in.ops = &preview_video_ops;
2300 prev->video_in.isp = to_isp_device(prev);
2301 prev->video_in.capture_mem = PAGE_ALIGN(4096 * 4096) * 2 * 3;
2302 prev->video_in.bpl_alignment = 64;
2303 prev->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2304 prev->video_out.ops = &preview_video_ops;
2305 prev->video_out.isp = to_isp_device(prev);
2306 prev->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 2 * 3;
2307 prev->video_out.bpl_alignment = 32;
2308
2309 ret = omap3isp_video_init(&prev->video_in, "preview");
2310 if (ret < 0)
2311 goto error_video_in;
2312
2313 ret = omap3isp_video_init(&prev->video_out, "preview");
2314 if (ret < 0)
2315 goto error_video_out;
2316
2317 return 0;
2318
2319error_video_out:
2320 omap3isp_video_cleanup(&prev->video_in);
2321error_video_in:
2322 media_entity_cleanup(&prev->subdev.entity);
2323error_handler_free:
2324 v4l2_ctrl_handler_free(&prev->ctrls);
2325 return ret;
2326}
2327
2328
2329
2330
2331
2332
2333int omap3isp_preview_init(struct isp_device *isp)
2334{
2335 struct isp_prev_device *prev = &isp->isp_prev;
2336
2337 init_waitqueue_head(&prev->wait);
2338
2339 preview_init_params(prev);
2340
2341 return preview_init_entities(prev);
2342}
2343
2344void omap3isp_preview_cleanup(struct isp_device *isp)
2345{
2346 struct isp_prev_device *prev = &isp->isp_prev;
2347
2348 v4l2_ctrl_handler_free(&prev->ctrls);
2349 omap3isp_video_cleanup(&prev->video_in);
2350 omap3isp_video_cleanup(&prev->video_out);
2351 media_entity_cleanup(&prev->subdev.entity);
2352}
2353