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
933 if (update == 0)
934 return;
935
936 for (i = 0; i < ARRAY_SIZE(update_attrs); i++) {
937 const struct preview_update *attr = &update_attrs[i];
938 struct prev_params *params;
939 unsigned int bit = 1 << i;
940
941 if (!(update & bit))
942 continue;
943
944 params = &prev->params.params[!(active & bit)];
945
946 if (params->features & bit) {
947 if (attr->config)
948 attr->config(prev, params);
949 if (attr->enable)
950 attr->enable(prev, true);
951 } else {
952 if (attr->enable)
953 attr->enable(prev, false);
954 }
955 }
956}
957
958
959
960
961
962
963static void preview_config_ycpos(struct isp_prev_device *prev, u32 pixelcode)
964{
965 struct isp_device *isp = to_isp_device(prev);
966 enum preview_ycpos_mode mode;
967
968 switch (pixelcode) {
969 case MEDIA_BUS_FMT_YUYV8_1X16:
970 mode = YCPOS_CrYCbY;
971 break;
972 case MEDIA_BUS_FMT_UYVY8_1X16:
973 mode = YCPOS_YCrYCb;
974 break;
975 default:
976 return;
977 }
978
979 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
980 ISPPRV_PCR_YCPOS_CrYCbY,
981 mode << ISPPRV_PCR_YCPOS_SHIFT);
982}
983
984
985
986
987
988static void preview_config_averager(struct isp_prev_device *prev, u8 average)
989{
990 struct isp_device *isp = to_isp_device(prev);
991
992 isp_reg_writel(isp, ISPPRV_AVE_EVENDIST_2 << ISPPRV_AVE_EVENDIST_SHIFT |
993 ISPPRV_AVE_ODDDIST_2 << ISPPRV_AVE_ODDDIST_SHIFT |
994 average, OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE);
995}
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011static void preview_config_input_format(struct isp_prev_device *prev,
1012 const struct isp_format_info *info)
1013{
1014 struct isp_device *isp = to_isp_device(prev);
1015 struct prev_params *params;
1016
1017 if (info->width == 8)
1018 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1019 ISPPRV_PCR_WIDTH);
1020 else
1021 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1022 ISPPRV_PCR_WIDTH);
1023
1024 switch (info->flavor) {
1025 case MEDIA_BUS_FMT_SGRBG8_1X8:
1026 prev->params.cfa_order = 0;
1027 break;
1028 case MEDIA_BUS_FMT_SRGGB8_1X8:
1029 prev->params.cfa_order = 1;
1030 break;
1031 case MEDIA_BUS_FMT_SBGGR8_1X8:
1032 prev->params.cfa_order = 2;
1033 break;
1034 case MEDIA_BUS_FMT_SGBRG8_1X8:
1035 prev->params.cfa_order = 3;
1036 break;
1037 default:
1038
1039 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1040 ISPPRV_PCR_CFAEN);
1041 return;
1042 }
1043
1044 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_CFAEN);
1045 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1046 ISPPRV_PCR_CFAFMT_MASK, ISPPRV_PCR_CFAFMT_BAYER);
1047
1048 params = (prev->params.active & OMAP3ISP_PREV_CFA)
1049 ? &prev->params.params[0] : &prev->params.params[1];
1050
1051 preview_config_cfa(prev, params);
1052}
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065static void preview_config_input_size(struct isp_prev_device *prev, u32 active)
1066{
1067 const struct v4l2_mbus_framefmt *format = &prev->formats[PREV_PAD_SINK];
1068 struct isp_device *isp = to_isp_device(prev);
1069 unsigned int sph = prev->crop.left;
1070 unsigned int eph = prev->crop.left + prev->crop.width - 1;
1071 unsigned int slv = prev->crop.top;
1072 unsigned int elv = prev->crop.top + prev->crop.height - 1;
1073 u32 features;
1074
1075 if (format->code != MEDIA_BUS_FMT_Y8_1X8 &&
1076 format->code != MEDIA_BUS_FMT_Y10_1X10) {
1077 sph -= 2;
1078 eph += 2;
1079 slv -= 2;
1080 elv += 2;
1081 }
1082
1083 features = (prev->params.params[0].features & active)
1084 | (prev->params.params[1].features & ~active);
1085
1086 if (features & (OMAP3ISP_PREV_DEFECT_COR | OMAP3ISP_PREV_NF)) {
1087 sph -= 2;
1088 eph += 2;
1089 slv -= 2;
1090 elv += 2;
1091 }
1092 if (features & OMAP3ISP_PREV_HRZ_MED) {
1093 sph -= 2;
1094 eph += 2;
1095 }
1096 if (features & (OMAP3ISP_PREV_CHROMA_SUPP | OMAP3ISP_PREV_LUMAENH))
1097 sph -= 2;
1098
1099 isp_reg_writel(isp, (sph << ISPPRV_HORZ_INFO_SPH_SHIFT) | eph,
1100 OMAP3_ISP_IOMEM_PREV, ISPPRV_HORZ_INFO);
1101 isp_reg_writel(isp, (slv << ISPPRV_VERT_INFO_SLV_SHIFT) | elv,
1102 OMAP3_ISP_IOMEM_PREV, ISPPRV_VERT_INFO);
1103}
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115static void
1116preview_config_inlineoffset(struct isp_prev_device *prev, u32 offset)
1117{
1118 struct isp_device *isp = to_isp_device(prev);
1119
1120 isp_reg_writel(isp, offset & 0xffff, OMAP3_ISP_IOMEM_PREV,
1121 ISPPRV_RADR_OFFSET);
1122}
1123
1124
1125
1126
1127
1128
1129
1130static void preview_set_inaddr(struct isp_prev_device *prev, u32 addr)
1131{
1132 struct isp_device *isp = to_isp_device(prev);
1133
1134 isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_PREV, ISPPRV_RSDR_ADDR);
1135}
1136
1137
1138
1139
1140
1141
1142
1143static void preview_config_outlineoffset(struct isp_prev_device *prev,
1144 u32 offset)
1145{
1146 struct isp_device *isp = to_isp_device(prev);
1147
1148 isp_reg_writel(isp, offset & 0xffff, OMAP3_ISP_IOMEM_PREV,
1149 ISPPRV_WADD_OFFSET);
1150}
1151
1152
1153
1154
1155
1156
1157
1158static void preview_set_outaddr(struct isp_prev_device *prev, u32 addr)
1159{
1160 struct isp_device *isp = to_isp_device(prev);
1161
1162 isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_PREV, ISPPRV_WSDR_ADDR);
1163}
1164
1165static void preview_adjust_bandwidth(struct isp_prev_device *prev)
1166{
1167 struct isp_pipeline *pipe = to_isp_pipeline(&prev->subdev.entity);
1168 struct isp_device *isp = to_isp_device(prev);
1169 const struct v4l2_mbus_framefmt *ifmt = &prev->formats[PREV_PAD_SINK];
1170 unsigned long l3_ick = pipe->l3_ick;
1171 struct v4l2_fract *timeperframe;
1172 unsigned int cycles_per_frame;
1173 unsigned int requests_per_frame;
1174 unsigned int cycles_per_request;
1175 unsigned int minimum;
1176 unsigned int maximum;
1177 unsigned int value;
1178
1179 if (prev->input != PREVIEW_INPUT_MEMORY) {
1180 isp_reg_clr(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_SDR_REQ_EXP,
1181 ISPSBL_SDR_REQ_PRV_EXP_MASK);
1182 return;
1183 }
1184
1185
1186
1187
1188
1189 cycles_per_request = div_u64((u64)l3_ick / 2 * 256 + pipe->max_rate - 1,
1190 pipe->max_rate);
1191 minimum = DIV_ROUND_UP(cycles_per_request, 32);
1192
1193
1194
1195
1196
1197
1198 timeperframe = &pipe->max_timeperframe;
1199
1200 requests_per_frame = DIV_ROUND_UP(ifmt->width * 2, 256) * ifmt->height;
1201 cycles_per_frame = div_u64((u64)l3_ick * timeperframe->numerator,
1202 timeperframe->denominator);
1203 cycles_per_request = cycles_per_frame / requests_per_frame;
1204
1205 maximum = cycles_per_request / 32;
1206
1207 value = max(minimum, maximum);
1208
1209 dev_dbg(isp->dev, "%s: cycles per request = %u\n", __func__, value);
1210 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_SDR_REQ_EXP,
1211 ISPSBL_SDR_REQ_PRV_EXP_MASK,
1212 value << ISPSBL_SDR_REQ_PRV_EXP_SHIFT);
1213}
1214
1215
1216
1217
1218int omap3isp_preview_busy(struct isp_prev_device *prev)
1219{
1220 struct isp_device *isp = to_isp_device(prev);
1221
1222 return isp_reg_readl(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR)
1223 & ISPPRV_PCR_BUSY;
1224}
1225
1226
1227
1228
1229void omap3isp_preview_restore_context(struct isp_device *isp)
1230{
1231 struct isp_prev_device *prev = &isp->isp_prev;
1232 const u32 update = OMAP3ISP_PREV_FEATURES_END - 1;
1233
1234 prev->params.params[0].update = prev->params.active & update;
1235 prev->params.params[1].update = ~prev->params.active & update;
1236
1237 preview_setup_hw(prev, update, prev->params.active);
1238
1239 prev->params.params[0].update = 0;
1240 prev->params.params[1].update = 0;
1241}
1242
1243
1244
1245
1246#define PREV_PRINT_REGISTER(isp, name)\
1247 dev_dbg(isp->dev, "###PRV " #name "=0x%08x\n", \
1248 isp_reg_readl(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_##name))
1249
1250static void preview_print_status(struct isp_prev_device *prev)
1251{
1252 struct isp_device *isp = to_isp_device(prev);
1253
1254 dev_dbg(isp->dev, "-------------Preview Register dump----------\n");
1255
1256 PREV_PRINT_REGISTER(isp, PCR);
1257 PREV_PRINT_REGISTER(isp, HORZ_INFO);
1258 PREV_PRINT_REGISTER(isp, VERT_INFO);
1259 PREV_PRINT_REGISTER(isp, RSDR_ADDR);
1260 PREV_PRINT_REGISTER(isp, RADR_OFFSET);
1261 PREV_PRINT_REGISTER(isp, DSDR_ADDR);
1262 PREV_PRINT_REGISTER(isp, DRKF_OFFSET);
1263 PREV_PRINT_REGISTER(isp, WSDR_ADDR);
1264 PREV_PRINT_REGISTER(isp, WADD_OFFSET);
1265 PREV_PRINT_REGISTER(isp, AVE);
1266 PREV_PRINT_REGISTER(isp, HMED);
1267 PREV_PRINT_REGISTER(isp, NF);
1268 PREV_PRINT_REGISTER(isp, WB_DGAIN);
1269 PREV_PRINT_REGISTER(isp, WBGAIN);
1270 PREV_PRINT_REGISTER(isp, WBSEL);
1271 PREV_PRINT_REGISTER(isp, CFA);
1272 PREV_PRINT_REGISTER(isp, BLKADJOFF);
1273 PREV_PRINT_REGISTER(isp, RGB_MAT1);
1274 PREV_PRINT_REGISTER(isp, RGB_MAT2);
1275 PREV_PRINT_REGISTER(isp, RGB_MAT3);
1276 PREV_PRINT_REGISTER(isp, RGB_MAT4);
1277 PREV_PRINT_REGISTER(isp, RGB_MAT5);
1278 PREV_PRINT_REGISTER(isp, RGB_OFF1);
1279 PREV_PRINT_REGISTER(isp, RGB_OFF2);
1280 PREV_PRINT_REGISTER(isp, CSC0);
1281 PREV_PRINT_REGISTER(isp, CSC1);
1282 PREV_PRINT_REGISTER(isp, CSC2);
1283 PREV_PRINT_REGISTER(isp, CSC_OFFSET);
1284 PREV_PRINT_REGISTER(isp, CNT_BRT);
1285 PREV_PRINT_REGISTER(isp, CSUP);
1286 PREV_PRINT_REGISTER(isp, SETUP_YC);
1287 PREV_PRINT_REGISTER(isp, SET_TBL_ADDR);
1288 PREV_PRINT_REGISTER(isp, CDC_THR0);
1289 PREV_PRINT_REGISTER(isp, CDC_THR1);
1290 PREV_PRINT_REGISTER(isp, CDC_THR2);
1291 PREV_PRINT_REGISTER(isp, CDC_THR3);
1292
1293 dev_dbg(isp->dev, "--------------------------------------------\n");
1294}
1295
1296
1297
1298
1299
1300static void preview_init_params(struct isp_prev_device *prev)
1301{
1302 struct prev_params *params;
1303 unsigned int i;
1304
1305 spin_lock_init(&prev->params.lock);
1306
1307 prev->params.active = ~0;
1308 prev->params.params[0].busy = 0;
1309 prev->params.params[0].update = OMAP3ISP_PREV_FEATURES_END - 1;
1310 prev->params.params[1].busy = 0;
1311 prev->params.params[1].update = 0;
1312
1313 params = &prev->params.params[0];
1314
1315
1316 params->contrast = ISPPRV_CONTRAST_DEF * ISPPRV_CONTRAST_UNITS;
1317 params->brightness = ISPPRV_BRIGHT_DEF * ISPPRV_BRIGHT_UNITS;
1318 params->cfa.format = OMAP3ISP_CFAFMT_BAYER;
1319 memcpy(params->cfa.table, cfa_coef_table,
1320 sizeof(params->cfa.table));
1321 params->cfa.gradthrs_horz = FLR_CFA_GRADTHRS_HORZ;
1322 params->cfa.gradthrs_vert = FLR_CFA_GRADTHRS_VERT;
1323 params->csup.gain = FLR_CSUP_GAIN;
1324 params->csup.thres = FLR_CSUP_THRES;
1325 params->csup.hypf_en = 0;
1326 memcpy(params->luma.table, luma_enhance_table,
1327 sizeof(params->luma.table));
1328 params->nf.spread = FLR_NF_STRGTH;
1329 memcpy(params->nf.table, noise_filter_table, sizeof(params->nf.table));
1330 params->dcor.couplet_mode_en = 1;
1331 for (i = 0; i < OMAP3ISP_PREV_DETECT_CORRECT_CHANNELS; i++)
1332 params->dcor.detect_correct[i] = DEF_DETECT_CORRECT_VAL;
1333 memcpy(params->gamma.blue, gamma_table, sizeof(params->gamma.blue));
1334 memcpy(params->gamma.green, gamma_table, sizeof(params->gamma.green));
1335 memcpy(params->gamma.red, gamma_table, sizeof(params->gamma.red));
1336 params->wbal.dgain = FLR_WBAL_DGAIN;
1337 params->wbal.coef0 = FLR_WBAL_COEF;
1338 params->wbal.coef1 = FLR_WBAL_COEF;
1339 params->wbal.coef2 = FLR_WBAL_COEF;
1340 params->wbal.coef3 = FLR_WBAL_COEF;
1341 params->blkadj.red = FLR_BLKADJ_RED;
1342 params->blkadj.green = FLR_BLKADJ_GREEN;
1343 params->blkadj.blue = FLR_BLKADJ_BLUE;
1344 params->rgb2rgb = flr_rgb2rgb;
1345 params->csc = flr_prev_csc;
1346 params->yclimit.minC = ISPPRV_YC_MIN;
1347 params->yclimit.maxC = ISPPRV_YC_MAX;
1348 params->yclimit.minY = ISPPRV_YC_MIN;
1349 params->yclimit.maxY = ISPPRV_YC_MAX;
1350
1351 params->features = OMAP3ISP_PREV_CFA | OMAP3ISP_PREV_DEFECT_COR
1352 | OMAP3ISP_PREV_NF | OMAP3ISP_PREV_GAMMA
1353 | OMAP3ISP_PREV_BLKADJ | OMAP3ISP_PREV_YC_LIMIT
1354 | OMAP3ISP_PREV_RGB2RGB | OMAP3ISP_PREV_COLOR_CONV
1355 | OMAP3ISP_PREV_WB | OMAP3ISP_PREV_BRIGHTNESS
1356 | OMAP3ISP_PREV_CONTRAST;
1357}
1358
1359
1360
1361
1362
1363
1364static unsigned int preview_max_out_width(struct isp_prev_device *prev)
1365{
1366 struct isp_device *isp = to_isp_device(prev);
1367
1368 switch (isp->revision) {
1369 case ISP_REVISION_1_0:
1370 return PREV_MAX_OUT_WIDTH_REV_1;
1371
1372 case ISP_REVISION_2_0:
1373 default:
1374 return PREV_MAX_OUT_WIDTH_REV_2;
1375
1376 case ISP_REVISION_15_0:
1377 return PREV_MAX_OUT_WIDTH_REV_15;
1378 }
1379}
1380
1381static void preview_configure(struct isp_prev_device *prev)
1382{
1383 struct isp_device *isp = to_isp_device(prev);
1384 const struct isp_format_info *info;
1385 struct v4l2_mbus_framefmt *format;
1386 unsigned long flags;
1387 u32 update;
1388 u32 active;
1389
1390 spin_lock_irqsave(&prev->params.lock, flags);
1391
1392 update = preview_params_lock(prev, 0, false);
1393 active = prev->params.active;
1394 spin_unlock_irqrestore(&prev->params.lock, flags);
1395
1396
1397 format = &prev->formats[PREV_PAD_SINK];
1398 info = omap3isp_video_format_info(format->code);
1399
1400 preview_adjust_bandwidth(prev);
1401
1402 preview_config_input_format(prev, info);
1403 preview_config_input_size(prev, active);
1404
1405 if (prev->input == PREVIEW_INPUT_CCDC)
1406 preview_config_inlineoffset(prev, 0);
1407 else
1408 preview_config_inlineoffset(prev, ALIGN(format->width, 0x20) *
1409 info->bpp);
1410
1411 preview_setup_hw(prev, update, active);
1412
1413
1414 format = &prev->formats[PREV_PAD_SOURCE];
1415
1416 if (prev->output & PREVIEW_OUTPUT_MEMORY)
1417 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1418 ISPPRV_PCR_SDRPORT);
1419 else
1420 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1421 ISPPRV_PCR_SDRPORT);
1422
1423 if (prev->output & PREVIEW_OUTPUT_RESIZER)
1424 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1425 ISPPRV_PCR_RSZPORT);
1426 else
1427 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1428 ISPPRV_PCR_RSZPORT);
1429
1430 if (prev->output & PREVIEW_OUTPUT_MEMORY)
1431 preview_config_outlineoffset(prev,
1432 ALIGN(format->width, 0x10) * 2);
1433
1434 preview_config_averager(prev, 0);
1435 preview_config_ycpos(prev, format->code);
1436
1437 spin_lock_irqsave(&prev->params.lock, flags);
1438 preview_params_unlock(prev, update, false);
1439 spin_unlock_irqrestore(&prev->params.lock, flags);
1440}
1441
1442
1443
1444
1445
1446static void preview_enable_oneshot(struct isp_prev_device *prev)
1447{
1448 struct isp_device *isp = to_isp_device(prev);
1449
1450
1451
1452
1453
1454 if (prev->input == PREVIEW_INPUT_MEMORY)
1455 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1456 ISPPRV_PCR_SOURCE);
1457
1458 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1459 ISPPRV_PCR_EN | ISPPRV_PCR_ONESHOT);
1460}
1461
1462void omap3isp_preview_isr_frame_sync(struct isp_prev_device *prev)
1463{
1464
1465
1466
1467
1468
1469
1470 if (prev->state == ISP_PIPELINE_STREAM_CONTINUOUS &&
1471 prev->video_out.dmaqueue_flags & ISP_VIDEO_DMAQUEUE_QUEUED) {
1472 preview_enable_oneshot(prev);
1473 isp_video_dmaqueue_flags_clr(&prev->video_out);
1474 }
1475}
1476
1477static void preview_isr_buffer(struct isp_prev_device *prev)
1478{
1479 struct isp_pipeline *pipe = to_isp_pipeline(&prev->subdev.entity);
1480 struct isp_buffer *buffer;
1481 int restart = 0;
1482
1483 if (prev->input == PREVIEW_INPUT_MEMORY) {
1484 buffer = omap3isp_video_buffer_next(&prev->video_in);
1485 if (buffer != NULL)
1486 preview_set_inaddr(prev, buffer->dma);
1487 pipe->state |= ISP_PIPELINE_IDLE_INPUT;
1488 }
1489
1490 if (prev->output & PREVIEW_OUTPUT_MEMORY) {
1491 buffer = omap3isp_video_buffer_next(&prev->video_out);
1492 if (buffer != NULL) {
1493 preview_set_outaddr(prev, buffer->dma);
1494 restart = 1;
1495 }
1496 pipe->state |= ISP_PIPELINE_IDLE_OUTPUT;
1497 }
1498
1499 switch (prev->state) {
1500 case ISP_PIPELINE_STREAM_SINGLESHOT:
1501 if (isp_pipeline_ready(pipe))
1502 omap3isp_pipeline_set_stream(pipe,
1503 ISP_PIPELINE_STREAM_SINGLESHOT);
1504 break;
1505
1506 case ISP_PIPELINE_STREAM_CONTINUOUS:
1507
1508
1509
1510 if (restart)
1511 preview_enable_oneshot(prev);
1512 break;
1513
1514 case ISP_PIPELINE_STREAM_STOPPED:
1515 default:
1516 return;
1517 }
1518}
1519
1520
1521
1522
1523
1524
1525void omap3isp_preview_isr(struct isp_prev_device *prev)
1526{
1527 unsigned long flags;
1528 u32 update;
1529 u32 active;
1530
1531 if (omap3isp_module_sync_is_stopping(&prev->wait, &prev->stopping))
1532 return;
1533
1534 spin_lock_irqsave(&prev->params.lock, flags);
1535 preview_params_switch(prev);
1536 update = preview_params_lock(prev, 0, false);
1537 active = prev->params.active;
1538 spin_unlock_irqrestore(&prev->params.lock, flags);
1539
1540 preview_setup_hw(prev, update, active);
1541 preview_config_input_size(prev, active);
1542
1543 if (prev->input == PREVIEW_INPUT_MEMORY ||
1544 prev->output & PREVIEW_OUTPUT_MEMORY)
1545 preview_isr_buffer(prev);
1546 else if (prev->state == ISP_PIPELINE_STREAM_CONTINUOUS)
1547 preview_enable_oneshot(prev);
1548
1549 spin_lock_irqsave(&prev->params.lock, flags);
1550 preview_params_unlock(prev, update, false);
1551 spin_unlock_irqrestore(&prev->params.lock, flags);
1552}
1553
1554
1555
1556
1557
1558static int preview_video_queue(struct isp_video *video,
1559 struct isp_buffer *buffer)
1560{
1561 struct isp_prev_device *prev = &video->isp->isp_prev;
1562
1563 if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
1564 preview_set_inaddr(prev, buffer->dma);
1565
1566 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1567 preview_set_outaddr(prev, buffer->dma);
1568
1569 return 0;
1570}
1571
1572static const struct isp_video_operations preview_video_ops = {
1573 .queue = preview_video_queue,
1574};
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584static int preview_s_ctrl(struct v4l2_ctrl *ctrl)
1585{
1586 struct isp_prev_device *prev =
1587 container_of(ctrl->handler, struct isp_prev_device, ctrls);
1588
1589 switch (ctrl->id) {
1590 case V4L2_CID_BRIGHTNESS:
1591 preview_update_brightness(prev, ctrl->val);
1592 break;
1593 case V4L2_CID_CONTRAST:
1594 preview_update_contrast(prev, ctrl->val);
1595 break;
1596 }
1597
1598 return 0;
1599}
1600
1601static const struct v4l2_ctrl_ops preview_ctrl_ops = {
1602 .s_ctrl = preview_s_ctrl,
1603};
1604
1605
1606
1607
1608
1609
1610
1611
1612static long preview_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
1613{
1614 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1615
1616 switch (cmd) {
1617 case VIDIOC_OMAP3ISP_PRV_CFG:
1618 return preview_config(prev, arg);
1619
1620 default:
1621 return -ENOIOCTLCMD;
1622 }
1623}
1624
1625
1626
1627
1628
1629
1630
1631static int preview_set_stream(struct v4l2_subdev *sd, int enable)
1632{
1633 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1634 struct isp_video *video_out = &prev->video_out;
1635 struct isp_device *isp = to_isp_device(prev);
1636 struct device *dev = to_device(prev);
1637
1638 if (prev->state == ISP_PIPELINE_STREAM_STOPPED) {
1639 if (enable == ISP_PIPELINE_STREAM_STOPPED)
1640 return 0;
1641
1642 omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_PREVIEW);
1643 preview_configure(prev);
1644 atomic_set(&prev->stopping, 0);
1645 preview_print_status(prev);
1646 }
1647
1648 switch (enable) {
1649 case ISP_PIPELINE_STREAM_CONTINUOUS:
1650 if (prev->output & PREVIEW_OUTPUT_MEMORY)
1651 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_PREVIEW_WRITE);
1652
1653 if (video_out->dmaqueue_flags & ISP_VIDEO_DMAQUEUE_QUEUED ||
1654 !(prev->output & PREVIEW_OUTPUT_MEMORY))
1655 preview_enable_oneshot(prev);
1656
1657 isp_video_dmaqueue_flags_clr(video_out);
1658 break;
1659
1660 case ISP_PIPELINE_STREAM_SINGLESHOT:
1661 if (prev->input == PREVIEW_INPUT_MEMORY)
1662 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_PREVIEW_READ);
1663 if (prev->output & PREVIEW_OUTPUT_MEMORY)
1664 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_PREVIEW_WRITE);
1665
1666 preview_enable_oneshot(prev);
1667 break;
1668
1669 case ISP_PIPELINE_STREAM_STOPPED:
1670 if (omap3isp_module_sync_idle(&sd->entity, &prev->wait,
1671 &prev->stopping))
1672 dev_dbg(dev, "%s: stop timeout.\n", sd->name);
1673 omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_PREVIEW_READ);
1674 omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_PREVIEW_WRITE);
1675 omap3isp_subclk_disable(isp, OMAP3_ISP_SUBCLK_PREVIEW);
1676 isp_video_dmaqueue_flags_clr(video_out);
1677 break;
1678 }
1679
1680 prev->state = enable;
1681 return 0;
1682}
1683
1684static struct v4l2_mbus_framefmt *
1685__preview_get_format(struct isp_prev_device *prev, struct v4l2_subdev_pad_config *cfg,
1686 unsigned int pad, enum v4l2_subdev_format_whence which)
1687{
1688 if (which == V4L2_SUBDEV_FORMAT_TRY)
1689 return v4l2_subdev_get_try_format(&prev->subdev, cfg, pad);
1690 else
1691 return &prev->formats[pad];
1692}
1693
1694static struct v4l2_rect *
1695__preview_get_crop(struct isp_prev_device *prev, struct v4l2_subdev_pad_config *cfg,
1696 enum v4l2_subdev_format_whence which)
1697{
1698 if (which == V4L2_SUBDEV_FORMAT_TRY)
1699 return v4l2_subdev_get_try_crop(&prev->subdev, cfg, PREV_PAD_SINK);
1700 else
1701 return &prev->crop;
1702}
1703
1704
1705static const unsigned int preview_input_fmts[] = {
1706 MEDIA_BUS_FMT_Y8_1X8,
1707 MEDIA_BUS_FMT_SGRBG8_1X8,
1708 MEDIA_BUS_FMT_SRGGB8_1X8,
1709 MEDIA_BUS_FMT_SBGGR8_1X8,
1710 MEDIA_BUS_FMT_SGBRG8_1X8,
1711 MEDIA_BUS_FMT_Y10_1X10,
1712 MEDIA_BUS_FMT_SGRBG10_1X10,
1713 MEDIA_BUS_FMT_SRGGB10_1X10,
1714 MEDIA_BUS_FMT_SBGGR10_1X10,
1715 MEDIA_BUS_FMT_SGBRG10_1X10,
1716};
1717
1718static const unsigned int preview_output_fmts[] = {
1719 MEDIA_BUS_FMT_UYVY8_1X16,
1720 MEDIA_BUS_FMT_YUYV8_1X16,
1721};
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734static void preview_try_format(struct isp_prev_device *prev,
1735 struct v4l2_subdev_pad_config *cfg, unsigned int pad,
1736 struct v4l2_mbus_framefmt *fmt,
1737 enum v4l2_subdev_format_whence which)
1738{
1739 u32 pixelcode;
1740 struct v4l2_rect *crop;
1741 unsigned int i;
1742
1743 switch (pad) {
1744 case PREV_PAD_SINK:
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754 if (prev->input == PREVIEW_INPUT_MEMORY) {
1755 fmt->width = clamp_t(u32, fmt->width, PREV_MIN_IN_WIDTH,
1756 preview_max_out_width(prev));
1757 fmt->height = clamp_t(u32, fmt->height,
1758 PREV_MIN_IN_HEIGHT,
1759 PREV_MAX_IN_HEIGHT);
1760 }
1761
1762 fmt->colorspace = V4L2_COLORSPACE_SRGB;
1763
1764 for (i = 0; i < ARRAY_SIZE(preview_input_fmts); i++) {
1765 if (fmt->code == preview_input_fmts[i])
1766 break;
1767 }
1768
1769
1770 if (i >= ARRAY_SIZE(preview_input_fmts))
1771 fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
1772 break;
1773
1774 case PREV_PAD_SOURCE:
1775 pixelcode = fmt->code;
1776 *fmt = *__preview_get_format(prev, cfg, PREV_PAD_SINK, which);
1777
1778 switch (pixelcode) {
1779 case MEDIA_BUS_FMT_YUYV8_1X16:
1780 case MEDIA_BUS_FMT_UYVY8_1X16:
1781 fmt->code = pixelcode;
1782 break;
1783
1784 default:
1785 fmt->code = MEDIA_BUS_FMT_YUYV8_1X16;
1786 break;
1787 }
1788
1789
1790
1791
1792
1793
1794 crop = __preview_get_crop(prev, cfg, which);
1795 fmt->width = crop->width;
1796 fmt->height = crop->height;
1797
1798 fmt->colorspace = V4L2_COLORSPACE_JPEG;
1799 break;
1800 }
1801
1802 fmt->field = V4L2_FIELD_NONE;
1803}
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817static void preview_try_crop(struct isp_prev_device *prev,
1818 const struct v4l2_mbus_framefmt *sink,
1819 struct v4l2_rect *crop)
1820{
1821 unsigned int left = PREV_MARGIN_LEFT;
1822 unsigned int right = sink->width - PREV_MARGIN_RIGHT;
1823 unsigned int top = PREV_MARGIN_TOP;
1824 unsigned int bottom = sink->height - PREV_MARGIN_BOTTOM;
1825
1826
1827
1828
1829
1830
1831 if (prev->input == PREVIEW_INPUT_CCDC) {
1832 left += 2;
1833 right -= 2;
1834 }
1835
1836
1837
1838
1839
1840 if (sink->code != MEDIA_BUS_FMT_Y8_1X8 &&
1841 sink->code != MEDIA_BUS_FMT_Y10_1X10) {
1842 left += 2;
1843 right -= 2;
1844 top += 2;
1845 bottom -= 2;
1846 }
1847
1848
1849 crop->left &= ~1;
1850 crop->top &= ~1;
1851
1852 crop->left = clamp_t(u32, crop->left, left, right - PREV_MIN_OUT_WIDTH);
1853 crop->top = clamp_t(u32, crop->top, top, bottom - PREV_MIN_OUT_HEIGHT);
1854 crop->width = clamp_t(u32, crop->width, PREV_MIN_OUT_WIDTH,
1855 right - crop->left);
1856 crop->height = clamp_t(u32, crop->height, PREV_MIN_OUT_HEIGHT,
1857 bottom - crop->top);
1858}
1859
1860
1861
1862
1863
1864
1865
1866
1867static int preview_enum_mbus_code(struct v4l2_subdev *sd,
1868 struct v4l2_subdev_pad_config *cfg,
1869 struct v4l2_subdev_mbus_code_enum *code)
1870{
1871 switch (code->pad) {
1872 case PREV_PAD_SINK:
1873 if (code->index >= ARRAY_SIZE(preview_input_fmts))
1874 return -EINVAL;
1875
1876 code->code = preview_input_fmts[code->index];
1877 break;
1878 case PREV_PAD_SOURCE:
1879 if (code->index >= ARRAY_SIZE(preview_output_fmts))
1880 return -EINVAL;
1881
1882 code->code = preview_output_fmts[code->index];
1883 break;
1884 default:
1885 return -EINVAL;
1886 }
1887
1888 return 0;
1889}
1890
1891static int preview_enum_frame_size(struct v4l2_subdev *sd,
1892 struct v4l2_subdev_pad_config *cfg,
1893 struct v4l2_subdev_frame_size_enum *fse)
1894{
1895 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1896 struct v4l2_mbus_framefmt format;
1897
1898 if (fse->index != 0)
1899 return -EINVAL;
1900
1901 format.code = fse->code;
1902 format.width = 1;
1903 format.height = 1;
1904 preview_try_format(prev, cfg, fse->pad, &format, fse->which);
1905 fse->min_width = format.width;
1906 fse->min_height = format.height;
1907
1908 if (format.code != fse->code)
1909 return -EINVAL;
1910
1911 format.code = fse->code;
1912 format.width = -1;
1913 format.height = -1;
1914 preview_try_format(prev, cfg, fse->pad, &format, fse->which);
1915 fse->max_width = format.width;
1916 fse->max_height = format.height;
1917
1918 return 0;
1919}
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931static int preview_get_selection(struct v4l2_subdev *sd,
1932 struct v4l2_subdev_pad_config *cfg,
1933 struct v4l2_subdev_selection *sel)
1934{
1935 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1936 struct v4l2_mbus_framefmt *format;
1937
1938 if (sel->pad != PREV_PAD_SINK)
1939 return -EINVAL;
1940
1941 switch (sel->target) {
1942 case V4L2_SEL_TGT_CROP_BOUNDS:
1943 sel->r.left = 0;
1944 sel->r.top = 0;
1945 sel->r.width = INT_MAX;
1946 sel->r.height = INT_MAX;
1947
1948 format = __preview_get_format(prev, cfg, PREV_PAD_SINK,
1949 sel->which);
1950 preview_try_crop(prev, format, &sel->r);
1951 break;
1952
1953 case V4L2_SEL_TGT_CROP:
1954 sel->r = *__preview_get_crop(prev, cfg, sel->which);
1955 break;
1956
1957 default:
1958 return -EINVAL;
1959 }
1960
1961 return 0;
1962}
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974static int preview_set_selection(struct v4l2_subdev *sd,
1975 struct v4l2_subdev_pad_config *cfg,
1976 struct v4l2_subdev_selection *sel)
1977{
1978 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1979 struct v4l2_mbus_framefmt *format;
1980
1981 if (sel->target != V4L2_SEL_TGT_CROP ||
1982 sel->pad != PREV_PAD_SINK)
1983 return -EINVAL;
1984
1985
1986 if (prev->state != ISP_PIPELINE_STREAM_STOPPED)
1987 return -EBUSY;
1988
1989
1990
1991
1992
1993 if (sel->flags & V4L2_SEL_FLAG_KEEP_CONFIG) {
1994 sel->r = *__preview_get_crop(prev, cfg, sel->which);
1995 return 0;
1996 }
1997
1998 format = __preview_get_format(prev, cfg, PREV_PAD_SINK, sel->which);
1999 preview_try_crop(prev, format, &sel->r);
2000 *__preview_get_crop(prev, cfg, sel->which) = sel->r;
2001
2002
2003 format = __preview_get_format(prev, cfg, PREV_PAD_SOURCE, sel->which);
2004 preview_try_format(prev, cfg, PREV_PAD_SOURCE, format, sel->which);
2005
2006 return 0;
2007}
2008
2009
2010
2011
2012
2013
2014
2015
2016static int preview_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
2017 struct v4l2_subdev_format *fmt)
2018{
2019 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
2020 struct v4l2_mbus_framefmt *format;
2021
2022 format = __preview_get_format(prev, cfg, fmt->pad, fmt->which);
2023 if (format == NULL)
2024 return -EINVAL;
2025
2026 fmt->format = *format;
2027 return 0;
2028}
2029
2030
2031
2032
2033
2034
2035
2036
2037static int preview_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
2038 struct v4l2_subdev_format *fmt)
2039{
2040 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
2041 struct v4l2_mbus_framefmt *format;
2042 struct v4l2_rect *crop;
2043
2044 format = __preview_get_format(prev, cfg, fmt->pad, fmt->which);
2045 if (format == NULL)
2046 return -EINVAL;
2047
2048 preview_try_format(prev, cfg, fmt->pad, &fmt->format, fmt->which);
2049 *format = fmt->format;
2050
2051
2052 if (fmt->pad == PREV_PAD_SINK) {
2053
2054 crop = __preview_get_crop(prev, cfg, fmt->which);
2055 crop->left = 0;
2056 crop->top = 0;
2057 crop->width = fmt->format.width;
2058 crop->height = fmt->format.height;
2059
2060 preview_try_crop(prev, &fmt->format, crop);
2061
2062
2063 format = __preview_get_format(prev, cfg, PREV_PAD_SOURCE,
2064 fmt->which);
2065 preview_try_format(prev, cfg, PREV_PAD_SOURCE, format,
2066 fmt->which);
2067 }
2068
2069 return 0;
2070}
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081static int preview_init_formats(struct v4l2_subdev *sd,
2082 struct v4l2_subdev_fh *fh)
2083{
2084 struct v4l2_subdev_format format;
2085
2086 memset(&format, 0, sizeof(format));
2087 format.pad = PREV_PAD_SINK;
2088 format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
2089 format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
2090 format.format.width = 4096;
2091 format.format.height = 4096;
2092 preview_set_format(sd, fh ? fh->pad : NULL, &format);
2093
2094 return 0;
2095}
2096
2097
2098static const struct v4l2_subdev_core_ops preview_v4l2_core_ops = {
2099 .ioctl = preview_ioctl,
2100};
2101
2102
2103static const struct v4l2_subdev_video_ops preview_v4l2_video_ops = {
2104 .s_stream = preview_set_stream,
2105};
2106
2107
2108static const struct v4l2_subdev_pad_ops preview_v4l2_pad_ops = {
2109 .enum_mbus_code = preview_enum_mbus_code,
2110 .enum_frame_size = preview_enum_frame_size,
2111 .get_fmt = preview_get_format,
2112 .set_fmt = preview_set_format,
2113 .get_selection = preview_get_selection,
2114 .set_selection = preview_set_selection,
2115};
2116
2117
2118static const struct v4l2_subdev_ops preview_v4l2_ops = {
2119 .core = &preview_v4l2_core_ops,
2120 .video = &preview_v4l2_video_ops,
2121 .pad = &preview_v4l2_pad_ops,
2122};
2123
2124
2125static const struct v4l2_subdev_internal_ops preview_v4l2_internal_ops = {
2126 .open = preview_init_formats,
2127};
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141static int preview_link_setup(struct media_entity *entity,
2142 const struct media_pad *local,
2143 const struct media_pad *remote, u32 flags)
2144{
2145 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
2146 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
2147
2148 switch (local->index | media_entity_type(remote->entity)) {
2149 case PREV_PAD_SINK | MEDIA_ENT_T_DEVNODE:
2150
2151 if (flags & MEDIA_LNK_FL_ENABLED) {
2152 if (prev->input == PREVIEW_INPUT_CCDC)
2153 return -EBUSY;
2154 prev->input = PREVIEW_INPUT_MEMORY;
2155 } else {
2156 if (prev->input == PREVIEW_INPUT_MEMORY)
2157 prev->input = PREVIEW_INPUT_NONE;
2158 }
2159 break;
2160
2161 case PREV_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
2162
2163 if (flags & MEDIA_LNK_FL_ENABLED) {
2164 if (prev->input == PREVIEW_INPUT_MEMORY)
2165 return -EBUSY;
2166 prev->input = PREVIEW_INPUT_CCDC;
2167 } else {
2168 if (prev->input == PREVIEW_INPUT_CCDC)
2169 prev->input = PREVIEW_INPUT_NONE;
2170 }
2171 break;
2172
2173
2174
2175
2176
2177
2178 case PREV_PAD_SOURCE | MEDIA_ENT_T_DEVNODE:
2179
2180 if (flags & MEDIA_LNK_FL_ENABLED) {
2181 if (prev->output & ~PREVIEW_OUTPUT_MEMORY)
2182 return -EBUSY;
2183 prev->output |= PREVIEW_OUTPUT_MEMORY;
2184 } else {
2185 prev->output &= ~PREVIEW_OUTPUT_MEMORY;
2186 }
2187 break;
2188
2189 case PREV_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV:
2190
2191 if (flags & MEDIA_LNK_FL_ENABLED) {
2192 if (prev->output & ~PREVIEW_OUTPUT_RESIZER)
2193 return -EBUSY;
2194 prev->output |= PREVIEW_OUTPUT_RESIZER;
2195 } else {
2196 prev->output &= ~PREVIEW_OUTPUT_RESIZER;
2197 }
2198 break;
2199
2200 default:
2201 return -EINVAL;
2202 }
2203
2204 return 0;
2205}
2206
2207
2208static const struct media_entity_operations preview_media_ops = {
2209 .link_setup = preview_link_setup,
2210 .link_validate = v4l2_subdev_link_validate,
2211};
2212
2213void omap3isp_preview_unregister_entities(struct isp_prev_device *prev)
2214{
2215 v4l2_device_unregister_subdev(&prev->subdev);
2216 omap3isp_video_unregister(&prev->video_in);
2217 omap3isp_video_unregister(&prev->video_out);
2218}
2219
2220int omap3isp_preview_register_entities(struct isp_prev_device *prev,
2221 struct v4l2_device *vdev)
2222{
2223 int ret;
2224
2225
2226 ret = v4l2_device_register_subdev(vdev, &prev->subdev);
2227 if (ret < 0)
2228 goto error;
2229
2230 ret = omap3isp_video_register(&prev->video_in, vdev);
2231 if (ret < 0)
2232 goto error;
2233
2234 ret = omap3isp_video_register(&prev->video_out, vdev);
2235 if (ret < 0)
2236 goto error;
2237
2238 return 0;
2239
2240error:
2241 omap3isp_preview_unregister_entities(prev);
2242 return ret;
2243}
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254static int preview_init_entities(struct isp_prev_device *prev)
2255{
2256 struct v4l2_subdev *sd = &prev->subdev;
2257 struct media_pad *pads = prev->pads;
2258 struct media_entity *me = &sd->entity;
2259 int ret;
2260
2261 prev->input = PREVIEW_INPUT_NONE;
2262
2263 v4l2_subdev_init(sd, &preview_v4l2_ops);
2264 sd->internal_ops = &preview_v4l2_internal_ops;
2265 strlcpy(sd->name, "OMAP3 ISP preview", sizeof(sd->name));
2266 sd->grp_id = 1 << 16;
2267 v4l2_set_subdevdata(sd, prev);
2268 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
2269
2270 v4l2_ctrl_handler_init(&prev->ctrls, 2);
2271 v4l2_ctrl_new_std(&prev->ctrls, &preview_ctrl_ops, V4L2_CID_BRIGHTNESS,
2272 ISPPRV_BRIGHT_LOW, ISPPRV_BRIGHT_HIGH,
2273 ISPPRV_BRIGHT_STEP, ISPPRV_BRIGHT_DEF);
2274 v4l2_ctrl_new_std(&prev->ctrls, &preview_ctrl_ops, V4L2_CID_CONTRAST,
2275 ISPPRV_CONTRAST_LOW, ISPPRV_CONTRAST_HIGH,
2276 ISPPRV_CONTRAST_STEP, ISPPRV_CONTRAST_DEF);
2277 v4l2_ctrl_handler_setup(&prev->ctrls);
2278 sd->ctrl_handler = &prev->ctrls;
2279
2280 pads[PREV_PAD_SINK].flags = MEDIA_PAD_FL_SINK
2281 | MEDIA_PAD_FL_MUST_CONNECT;
2282 pads[PREV_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
2283
2284 me->ops = &preview_media_ops;
2285 ret = media_entity_init(me, PREV_PADS_NUM, pads, 0);
2286 if (ret < 0)
2287 return ret;
2288
2289 preview_init_formats(sd, NULL);
2290
2291
2292
2293
2294
2295 prev->video_in.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
2296 prev->video_in.ops = &preview_video_ops;
2297 prev->video_in.isp = to_isp_device(prev);
2298 prev->video_in.capture_mem = PAGE_ALIGN(4096 * 4096) * 2 * 3;
2299 prev->video_in.bpl_alignment = 64;
2300 prev->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2301 prev->video_out.ops = &preview_video_ops;
2302 prev->video_out.isp = to_isp_device(prev);
2303 prev->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 2 * 3;
2304 prev->video_out.bpl_alignment = 32;
2305
2306 ret = omap3isp_video_init(&prev->video_in, "preview");
2307 if (ret < 0)
2308 goto error_video_in;
2309
2310 ret = omap3isp_video_init(&prev->video_out, "preview");
2311 if (ret < 0)
2312 goto error_video_out;
2313
2314
2315 ret = media_entity_create_link(&prev->video_in.video.entity, 0,
2316 &prev->subdev.entity, PREV_PAD_SINK, 0);
2317 if (ret < 0)
2318 goto error_link;
2319
2320 ret = media_entity_create_link(&prev->subdev.entity, PREV_PAD_SOURCE,
2321 &prev->video_out.video.entity, 0, 0);
2322 if (ret < 0)
2323 goto error_link;
2324
2325 return 0;
2326
2327error_link:
2328 omap3isp_video_cleanup(&prev->video_out);
2329error_video_out:
2330 omap3isp_video_cleanup(&prev->video_in);
2331error_video_in:
2332 media_entity_cleanup(&prev->subdev.entity);
2333 return ret;
2334}
2335
2336
2337
2338
2339
2340
2341int omap3isp_preview_init(struct isp_device *isp)
2342{
2343 struct isp_prev_device *prev = &isp->isp_prev;
2344
2345 init_waitqueue_head(&prev->wait);
2346
2347 preview_init_params(prev);
2348
2349 return preview_init_entities(prev);
2350}
2351
2352void omap3isp_preview_cleanup(struct isp_device *isp)
2353{
2354 struct isp_prev_device *prev = &isp->isp_prev;
2355
2356 v4l2_ctrl_handler_free(&prev->ctrls);
2357 omap3isp_video_cleanup(&prev->video_in);
2358 omap3isp_video_cleanup(&prev->video_out);
2359 media_entity_cleanup(&prev->subdev.entity);
2360}
2361