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,
1683 struct v4l2_subdev_state *sd_state,
1684 unsigned int pad, enum v4l2_subdev_format_whence which)
1685{
1686 if (which == V4L2_SUBDEV_FORMAT_TRY)
1687 return v4l2_subdev_get_try_format(&prev->subdev, sd_state,
1688 pad);
1689 else
1690 return &prev->formats[pad];
1691}
1692
1693static struct v4l2_rect *
1694__preview_get_crop(struct isp_prev_device *prev,
1695 struct v4l2_subdev_state *sd_state,
1696 enum v4l2_subdev_format_whence which)
1697{
1698 if (which == V4L2_SUBDEV_FORMAT_TRY)
1699 return v4l2_subdev_get_try_crop(&prev->subdev, sd_state,
1700 PREV_PAD_SINK);
1701 else
1702 return &prev->crop;
1703}
1704
1705
1706static const unsigned int preview_input_fmts[] = {
1707 MEDIA_BUS_FMT_Y8_1X8,
1708 MEDIA_BUS_FMT_SGRBG8_1X8,
1709 MEDIA_BUS_FMT_SRGGB8_1X8,
1710 MEDIA_BUS_FMT_SBGGR8_1X8,
1711 MEDIA_BUS_FMT_SGBRG8_1X8,
1712 MEDIA_BUS_FMT_Y10_1X10,
1713 MEDIA_BUS_FMT_SGRBG10_1X10,
1714 MEDIA_BUS_FMT_SRGGB10_1X10,
1715 MEDIA_BUS_FMT_SBGGR10_1X10,
1716 MEDIA_BUS_FMT_SGBRG10_1X10,
1717};
1718
1719static const unsigned int preview_output_fmts[] = {
1720 MEDIA_BUS_FMT_UYVY8_1X16,
1721 MEDIA_BUS_FMT_YUYV8_1X16,
1722};
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735static void preview_try_format(struct isp_prev_device *prev,
1736 struct v4l2_subdev_state *sd_state,
1737 unsigned int pad,
1738 struct v4l2_mbus_framefmt *fmt,
1739 enum v4l2_subdev_format_whence which)
1740{
1741 u32 pixelcode;
1742 struct v4l2_rect *crop;
1743 unsigned int i;
1744
1745 switch (pad) {
1746 case PREV_PAD_SINK:
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756 if (prev->input == PREVIEW_INPUT_MEMORY) {
1757 fmt->width = clamp_t(u32, fmt->width, PREV_MIN_IN_WIDTH,
1758 preview_max_out_width(prev));
1759 fmt->height = clamp_t(u32, fmt->height,
1760 PREV_MIN_IN_HEIGHT,
1761 PREV_MAX_IN_HEIGHT);
1762 }
1763
1764 fmt->colorspace = V4L2_COLORSPACE_SRGB;
1765
1766 for (i = 0; i < ARRAY_SIZE(preview_input_fmts); i++) {
1767 if (fmt->code == preview_input_fmts[i])
1768 break;
1769 }
1770
1771
1772 if (i >= ARRAY_SIZE(preview_input_fmts))
1773 fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
1774 break;
1775
1776 case PREV_PAD_SOURCE:
1777 pixelcode = fmt->code;
1778 *fmt = *__preview_get_format(prev, sd_state, PREV_PAD_SINK,
1779 which);
1780
1781 switch (pixelcode) {
1782 case MEDIA_BUS_FMT_YUYV8_1X16:
1783 case MEDIA_BUS_FMT_UYVY8_1X16:
1784 fmt->code = pixelcode;
1785 break;
1786
1787 default:
1788 fmt->code = MEDIA_BUS_FMT_YUYV8_1X16;
1789 break;
1790 }
1791
1792
1793
1794
1795
1796
1797 crop = __preview_get_crop(prev, sd_state, which);
1798 fmt->width = crop->width;
1799 fmt->height = crop->height;
1800
1801 fmt->colorspace = V4L2_COLORSPACE_JPEG;
1802 break;
1803 }
1804
1805 fmt->field = V4L2_FIELD_NONE;
1806}
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820static void preview_try_crop(struct isp_prev_device *prev,
1821 const struct v4l2_mbus_framefmt *sink,
1822 struct v4l2_rect *crop)
1823{
1824 unsigned int left = PREV_MARGIN_LEFT;
1825 unsigned int right = sink->width - PREV_MARGIN_RIGHT;
1826 unsigned int top = PREV_MARGIN_TOP;
1827 unsigned int bottom = sink->height - PREV_MARGIN_BOTTOM;
1828
1829
1830
1831
1832
1833
1834 if (prev->input == PREVIEW_INPUT_CCDC) {
1835 left += 2;
1836 right -= 2;
1837 }
1838
1839
1840
1841
1842
1843 if (sink->code != MEDIA_BUS_FMT_Y8_1X8 &&
1844 sink->code != MEDIA_BUS_FMT_Y10_1X10) {
1845 left += 2;
1846 right -= 2;
1847 top += 2;
1848 bottom -= 2;
1849 }
1850
1851
1852 crop->left &= ~1;
1853 crop->top &= ~1;
1854
1855 crop->left = clamp_t(u32, crop->left, left, right - PREV_MIN_OUT_WIDTH);
1856 crop->top = clamp_t(u32, crop->top, top, bottom - PREV_MIN_OUT_HEIGHT);
1857 crop->width = clamp_t(u32, crop->width, PREV_MIN_OUT_WIDTH,
1858 right - crop->left);
1859 crop->height = clamp_t(u32, crop->height, PREV_MIN_OUT_HEIGHT,
1860 bottom - crop->top);
1861}
1862
1863
1864
1865
1866
1867
1868
1869
1870static int preview_enum_mbus_code(struct v4l2_subdev *sd,
1871 struct v4l2_subdev_state *sd_state,
1872 struct v4l2_subdev_mbus_code_enum *code)
1873{
1874 switch (code->pad) {
1875 case PREV_PAD_SINK:
1876 if (code->index >= ARRAY_SIZE(preview_input_fmts))
1877 return -EINVAL;
1878
1879 code->code = preview_input_fmts[code->index];
1880 break;
1881 case PREV_PAD_SOURCE:
1882 if (code->index >= ARRAY_SIZE(preview_output_fmts))
1883 return -EINVAL;
1884
1885 code->code = preview_output_fmts[code->index];
1886 break;
1887 default:
1888 return -EINVAL;
1889 }
1890
1891 return 0;
1892}
1893
1894static int preview_enum_frame_size(struct v4l2_subdev *sd,
1895 struct v4l2_subdev_state *sd_state,
1896 struct v4l2_subdev_frame_size_enum *fse)
1897{
1898 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1899 struct v4l2_mbus_framefmt format;
1900
1901 if (fse->index != 0)
1902 return -EINVAL;
1903
1904 format.code = fse->code;
1905 format.width = 1;
1906 format.height = 1;
1907 preview_try_format(prev, sd_state, fse->pad, &format, fse->which);
1908 fse->min_width = format.width;
1909 fse->min_height = format.height;
1910
1911 if (format.code != fse->code)
1912 return -EINVAL;
1913
1914 format.code = fse->code;
1915 format.width = -1;
1916 format.height = -1;
1917 preview_try_format(prev, sd_state, fse->pad, &format, fse->which);
1918 fse->max_width = format.width;
1919 fse->max_height = format.height;
1920
1921 return 0;
1922}
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934static int preview_get_selection(struct v4l2_subdev *sd,
1935 struct v4l2_subdev_state *sd_state,
1936 struct v4l2_subdev_selection *sel)
1937{
1938 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1939 struct v4l2_mbus_framefmt *format;
1940
1941 if (sel->pad != PREV_PAD_SINK)
1942 return -EINVAL;
1943
1944 switch (sel->target) {
1945 case V4L2_SEL_TGT_CROP_BOUNDS:
1946 sel->r.left = 0;
1947 sel->r.top = 0;
1948 sel->r.width = INT_MAX;
1949 sel->r.height = INT_MAX;
1950
1951 format = __preview_get_format(prev, sd_state, PREV_PAD_SINK,
1952 sel->which);
1953 preview_try_crop(prev, format, &sel->r);
1954 break;
1955
1956 case V4L2_SEL_TGT_CROP:
1957 sel->r = *__preview_get_crop(prev, sd_state, sel->which);
1958 break;
1959
1960 default:
1961 return -EINVAL;
1962 }
1963
1964 return 0;
1965}
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977static int preview_set_selection(struct v4l2_subdev *sd,
1978 struct v4l2_subdev_state *sd_state,
1979 struct v4l2_subdev_selection *sel)
1980{
1981 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1982 struct v4l2_mbus_framefmt *format;
1983
1984 if (sel->target != V4L2_SEL_TGT_CROP ||
1985 sel->pad != PREV_PAD_SINK)
1986 return -EINVAL;
1987
1988
1989 if (prev->state != ISP_PIPELINE_STREAM_STOPPED)
1990 return -EBUSY;
1991
1992
1993
1994
1995
1996 if (sel->flags & V4L2_SEL_FLAG_KEEP_CONFIG) {
1997 sel->r = *__preview_get_crop(prev, sd_state, sel->which);
1998 return 0;
1999 }
2000
2001 format = __preview_get_format(prev, sd_state, PREV_PAD_SINK,
2002 sel->which);
2003 preview_try_crop(prev, format, &sel->r);
2004 *__preview_get_crop(prev, sd_state, sel->which) = sel->r;
2005
2006
2007 format = __preview_get_format(prev, sd_state, PREV_PAD_SOURCE,
2008 sel->which);
2009 preview_try_format(prev, sd_state, PREV_PAD_SOURCE, format,
2010 sel->which);
2011
2012 return 0;
2013}
2014
2015
2016
2017
2018
2019
2020
2021
2022static int preview_get_format(struct v4l2_subdev *sd,
2023 struct v4l2_subdev_state *sd_state,
2024 struct v4l2_subdev_format *fmt)
2025{
2026 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
2027 struct v4l2_mbus_framefmt *format;
2028
2029 format = __preview_get_format(prev, sd_state, fmt->pad, fmt->which);
2030 if (format == NULL)
2031 return -EINVAL;
2032
2033 fmt->format = *format;
2034 return 0;
2035}
2036
2037
2038
2039
2040
2041
2042
2043
2044static int preview_set_format(struct v4l2_subdev *sd,
2045 struct v4l2_subdev_state *sd_state,
2046 struct v4l2_subdev_format *fmt)
2047{
2048 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
2049 struct v4l2_mbus_framefmt *format;
2050 struct v4l2_rect *crop;
2051
2052 format = __preview_get_format(prev, sd_state, fmt->pad, fmt->which);
2053 if (format == NULL)
2054 return -EINVAL;
2055
2056 preview_try_format(prev, sd_state, fmt->pad, &fmt->format, fmt->which);
2057 *format = fmt->format;
2058
2059
2060 if (fmt->pad == PREV_PAD_SINK) {
2061
2062 crop = __preview_get_crop(prev, sd_state, fmt->which);
2063 crop->left = 0;
2064 crop->top = 0;
2065 crop->width = fmt->format.width;
2066 crop->height = fmt->format.height;
2067
2068 preview_try_crop(prev, &fmt->format, crop);
2069
2070
2071 format = __preview_get_format(prev, sd_state, PREV_PAD_SOURCE,
2072 fmt->which);
2073 preview_try_format(prev, sd_state, PREV_PAD_SOURCE, format,
2074 fmt->which);
2075 }
2076
2077 return 0;
2078}
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089static int preview_init_formats(struct v4l2_subdev *sd,
2090 struct v4l2_subdev_fh *fh)
2091{
2092 struct v4l2_subdev_format format;
2093
2094 memset(&format, 0, sizeof(format));
2095 format.pad = PREV_PAD_SINK;
2096 format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
2097 format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
2098 format.format.width = 4096;
2099 format.format.height = 4096;
2100 preview_set_format(sd, fh ? fh->state : NULL, &format);
2101
2102 return 0;
2103}
2104
2105
2106static const struct v4l2_subdev_core_ops preview_v4l2_core_ops = {
2107 .ioctl = preview_ioctl,
2108};
2109
2110
2111static const struct v4l2_subdev_video_ops preview_v4l2_video_ops = {
2112 .s_stream = preview_set_stream,
2113};
2114
2115
2116static const struct v4l2_subdev_pad_ops preview_v4l2_pad_ops = {
2117 .enum_mbus_code = preview_enum_mbus_code,
2118 .enum_frame_size = preview_enum_frame_size,
2119 .get_fmt = preview_get_format,
2120 .set_fmt = preview_set_format,
2121 .get_selection = preview_get_selection,
2122 .set_selection = preview_set_selection,
2123};
2124
2125
2126static const struct v4l2_subdev_ops preview_v4l2_ops = {
2127 .core = &preview_v4l2_core_ops,
2128 .video = &preview_v4l2_video_ops,
2129 .pad = &preview_v4l2_pad_ops,
2130};
2131
2132
2133static const struct v4l2_subdev_internal_ops preview_v4l2_internal_ops = {
2134 .open = preview_init_formats,
2135};
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149static int preview_link_setup(struct media_entity *entity,
2150 const struct media_pad *local,
2151 const struct media_pad *remote, u32 flags)
2152{
2153 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
2154 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
2155 unsigned int index = local->index;
2156
2157
2158 if (is_media_entity_v4l2_subdev(remote->entity))
2159 index |= 2 << 16;
2160
2161 switch (index) {
2162 case PREV_PAD_SINK:
2163
2164 if (flags & MEDIA_LNK_FL_ENABLED) {
2165 if (prev->input == PREVIEW_INPUT_CCDC)
2166 return -EBUSY;
2167 prev->input = PREVIEW_INPUT_MEMORY;
2168 } else {
2169 if (prev->input == PREVIEW_INPUT_MEMORY)
2170 prev->input = PREVIEW_INPUT_NONE;
2171 }
2172 break;
2173
2174 case PREV_PAD_SINK | 2 << 16:
2175
2176 if (flags & MEDIA_LNK_FL_ENABLED) {
2177 if (prev->input == PREVIEW_INPUT_MEMORY)
2178 return -EBUSY;
2179 prev->input = PREVIEW_INPUT_CCDC;
2180 } else {
2181 if (prev->input == PREVIEW_INPUT_CCDC)
2182 prev->input = PREVIEW_INPUT_NONE;
2183 }
2184 break;
2185
2186
2187
2188
2189
2190
2191 case PREV_PAD_SOURCE:
2192
2193 if (flags & MEDIA_LNK_FL_ENABLED) {
2194 if (prev->output & ~PREVIEW_OUTPUT_MEMORY)
2195 return -EBUSY;
2196 prev->output |= PREVIEW_OUTPUT_MEMORY;
2197 } else {
2198 prev->output &= ~PREVIEW_OUTPUT_MEMORY;
2199 }
2200 break;
2201
2202 case PREV_PAD_SOURCE | 2 << 16:
2203
2204 if (flags & MEDIA_LNK_FL_ENABLED) {
2205 if (prev->output & ~PREVIEW_OUTPUT_RESIZER)
2206 return -EBUSY;
2207 prev->output |= PREVIEW_OUTPUT_RESIZER;
2208 } else {
2209 prev->output &= ~PREVIEW_OUTPUT_RESIZER;
2210 }
2211 break;
2212
2213 default:
2214 return -EINVAL;
2215 }
2216
2217 return 0;
2218}
2219
2220
2221static const struct media_entity_operations preview_media_ops = {
2222 .link_setup = preview_link_setup,
2223 .link_validate = v4l2_subdev_link_validate,
2224};
2225
2226void omap3isp_preview_unregister_entities(struct isp_prev_device *prev)
2227{
2228 v4l2_device_unregister_subdev(&prev->subdev);
2229 omap3isp_video_unregister(&prev->video_in);
2230 omap3isp_video_unregister(&prev->video_out);
2231}
2232
2233int omap3isp_preview_register_entities(struct isp_prev_device *prev,
2234 struct v4l2_device *vdev)
2235{
2236 int ret;
2237
2238
2239 prev->subdev.dev = vdev->mdev->dev;
2240 ret = v4l2_device_register_subdev(vdev, &prev->subdev);
2241 if (ret < 0)
2242 goto error;
2243
2244 ret = omap3isp_video_register(&prev->video_in, vdev);
2245 if (ret < 0)
2246 goto error;
2247
2248 ret = omap3isp_video_register(&prev->video_out, vdev);
2249 if (ret < 0)
2250 goto error;
2251
2252 return 0;
2253
2254error:
2255 omap3isp_preview_unregister_entities(prev);
2256 return ret;
2257}
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268static int preview_init_entities(struct isp_prev_device *prev)
2269{
2270 struct v4l2_subdev *sd = &prev->subdev;
2271 struct media_pad *pads = prev->pads;
2272 struct media_entity *me = &sd->entity;
2273 int ret;
2274
2275 prev->input = PREVIEW_INPUT_NONE;
2276
2277 v4l2_subdev_init(sd, &preview_v4l2_ops);
2278 sd->internal_ops = &preview_v4l2_internal_ops;
2279 strscpy(sd->name, "OMAP3 ISP preview", sizeof(sd->name));
2280 sd->grp_id = 1 << 16;
2281 v4l2_set_subdevdata(sd, prev);
2282 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
2283
2284 v4l2_ctrl_handler_init(&prev->ctrls, 2);
2285 v4l2_ctrl_new_std(&prev->ctrls, &preview_ctrl_ops, V4L2_CID_BRIGHTNESS,
2286 ISPPRV_BRIGHT_LOW, ISPPRV_BRIGHT_HIGH,
2287 ISPPRV_BRIGHT_STEP, ISPPRV_BRIGHT_DEF);
2288 v4l2_ctrl_new_std(&prev->ctrls, &preview_ctrl_ops, V4L2_CID_CONTRAST,
2289 ISPPRV_CONTRAST_LOW, ISPPRV_CONTRAST_HIGH,
2290 ISPPRV_CONTRAST_STEP, ISPPRV_CONTRAST_DEF);
2291 v4l2_ctrl_handler_setup(&prev->ctrls);
2292 sd->ctrl_handler = &prev->ctrls;
2293
2294 pads[PREV_PAD_SINK].flags = MEDIA_PAD_FL_SINK
2295 | MEDIA_PAD_FL_MUST_CONNECT;
2296 pads[PREV_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
2297
2298 me->ops = &preview_media_ops;
2299 ret = media_entity_pads_init(me, PREV_PADS_NUM, pads);
2300 if (ret < 0)
2301 goto error_handler_free;
2302
2303 preview_init_formats(sd, NULL);
2304
2305
2306
2307
2308
2309 prev->video_in.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
2310 prev->video_in.ops = &preview_video_ops;
2311 prev->video_in.isp = to_isp_device(prev);
2312 prev->video_in.capture_mem = PAGE_ALIGN(4096 * 4096) * 2 * 3;
2313 prev->video_in.bpl_alignment = 64;
2314 prev->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2315 prev->video_out.ops = &preview_video_ops;
2316 prev->video_out.isp = to_isp_device(prev);
2317 prev->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 2 * 3;
2318 prev->video_out.bpl_alignment = 32;
2319
2320 ret = omap3isp_video_init(&prev->video_in, "preview");
2321 if (ret < 0)
2322 goto error_video_in;
2323
2324 ret = omap3isp_video_init(&prev->video_out, "preview");
2325 if (ret < 0)
2326 goto error_video_out;
2327
2328 return 0;
2329
2330error_video_out:
2331 omap3isp_video_cleanup(&prev->video_in);
2332error_video_in:
2333 media_entity_cleanup(&prev->subdev.entity);
2334error_handler_free:
2335 v4l2_ctrl_handler_free(&prev->ctrls);
2336 return ret;
2337}
2338
2339
2340
2341
2342
2343
2344int omap3isp_preview_init(struct isp_device *isp)
2345{
2346 struct isp_prev_device *prev = &isp->isp_prev;
2347
2348 init_waitqueue_head(&prev->wait);
2349
2350 preview_init_params(prev);
2351
2352 return preview_init_entities(prev);
2353}
2354
2355void omap3isp_preview_cleanup(struct isp_device *isp)
2356{
2357 struct isp_prev_device *prev = &isp->isp_prev;
2358
2359 v4l2_ctrl_handler_free(&prev->ctrls);
2360 omap3isp_video_cleanup(&prev->video_in);
2361 omap3isp_video_cleanup(&prev->video_out);
2362 media_entity_cleanup(&prev->subdev.entity);
2363}
2364