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