1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#include <linux/device.h>
28#include <linux/mm.h>
29#include <linux/module.h>
30#include <linux/mutex.h>
31#include <linux/uaccess.h>
32
33#include "isp.h"
34#include "ispreg.h"
35#include "isppreview.h"
36
37
38static struct omap3isp_prev_rgbtorgb flr_rgb2rgb = {
39 {
40 {0x01E2, 0x0F30, 0x0FEE},
41 {0x0F9B, 0x01AC, 0x0FB9},
42 {0x0FE0, 0x0EC0, 0x0260}
43 },
44 {0x0000, 0x0000, 0x0000}
45};
46
47
48static struct omap3isp_prev_csc flr_prev_csc = {
49 {
50 {66, 129, 25},
51 {-38, -75, 112},
52 {112, -94 , -18}
53 },
54 {0x0, 0x0, 0x0}
55};
56
57
58#define FLR_CFA_GRADTHRS_HORZ 0x28
59#define FLR_CFA_GRADTHRS_VERT 0x28
60
61
62#define FLR_CSUP_GAIN 0x0D
63#define FLR_CSUP_THRES 0xEB
64
65
66#define FLR_NF_STRGTH 0x03
67
68
69#define FLR_WBAL_DGAIN 0x100
70#define FLR_WBAL_COEF 0x20
71
72
73#define FLR_BLKADJ_BLUE 0x0
74#define FLR_BLKADJ_GREEN 0x0
75#define FLR_BLKADJ_RED 0x0
76
77#define DEF_DETECT_CORRECT_VAL 0xe
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109#define PREV_MARGIN_LEFT 6
110#define PREV_MARGIN_RIGHT 4
111#define PREV_MARGIN_TOP 2
112#define PREV_MARGIN_BOTTOM 2
113
114#define PREV_MIN_IN_WIDTH 64
115#define PREV_MIN_IN_HEIGHT 8
116#define PREV_MAX_IN_HEIGHT 16384
117
118#define PREV_MIN_OUT_WIDTH 0
119#define PREV_MIN_OUT_HEIGHT 0
120#define PREV_MAX_OUT_WIDTH_REV_1 1280
121#define PREV_MAX_OUT_WIDTH_REV_2 3300
122#define PREV_MAX_OUT_WIDTH_REV_15 4096
123
124
125
126
127
128
129
130
131
132
133static u32 cfa_coef_table[4][OMAP3ISP_PREV_CFA_BLK_SIZE] = {
134#include "cfa_coef_table.h"
135};
136
137
138
139
140static u32 gamma_table[] = {
141#include "gamma_table.h"
142};
143
144
145
146
147static u32 noise_filter_table[] = {
148#include "noise_filter_table.h"
149};
150
151
152
153
154static u32 luma_enhance_table[] = {
155#include "luma_enhance_table.h"
156};
157
158
159
160
161static void
162preview_config_luma_enhancement(struct isp_prev_device *prev,
163 const struct prev_params *params)
164{
165 struct isp_device *isp = to_isp_device(prev);
166 const struct omap3isp_prev_luma *yt = ¶ms->luma;
167 unsigned int i;
168
169 isp_reg_writel(isp, ISPPRV_YENH_TABLE_ADDR,
170 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
171 for (i = 0; i < OMAP3ISP_PREV_YENH_TBL_SIZE; i++) {
172 isp_reg_writel(isp, yt->table[i],
173 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
174 }
175}
176
177
178
179
180static void
181preview_enable_luma_enhancement(struct isp_prev_device *prev, bool enable)
182{
183 struct isp_device *isp = to_isp_device(prev);
184
185 if (enable)
186 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
187 ISPPRV_PCR_YNENHEN);
188 else
189 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
190 ISPPRV_PCR_YNENHEN);
191}
192
193
194
195
196static void preview_enable_invalaw(struct isp_prev_device *prev, bool enable)
197{
198 struct isp_device *isp = to_isp_device(prev);
199
200 if (enable)
201 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
202 ISPPRV_PCR_INVALAW);
203 else
204 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
205 ISPPRV_PCR_INVALAW);
206}
207
208
209
210
211static void preview_config_hmed(struct isp_prev_device *prev,
212 const struct prev_params *params)
213{
214 struct isp_device *isp = to_isp_device(prev);
215 const struct omap3isp_prev_hmed *hmed = ¶ms->hmed;
216
217 isp_reg_writel(isp, (hmed->odddist == 1 ? 0 : ISPPRV_HMED_ODDDIST) |
218 (hmed->evendist == 1 ? 0 : ISPPRV_HMED_EVENDIST) |
219 (hmed->thres << ISPPRV_HMED_THRESHOLD_SHIFT),
220 OMAP3_ISP_IOMEM_PREV, ISPPRV_HMED);
221}
222
223
224
225
226static void preview_enable_hmed(struct isp_prev_device *prev, bool enable)
227{
228 struct isp_device *isp = to_isp_device(prev);
229
230 if (enable)
231 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
232 ISPPRV_PCR_HMEDEN);
233 else
234 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
235 ISPPRV_PCR_HMEDEN);
236}
237
238
239
240
241
242
243
244
245
246static void preview_config_cfa(struct isp_prev_device *prev,
247 const struct prev_params *params)
248{
249 static const unsigned int cfa_coef_order[4][4] = {
250 { 0, 1, 2, 3 },
251 { 1, 0, 3, 2 },
252 { 2, 3, 0, 1 },
253 { 3, 2, 1, 0 },
254 };
255 const unsigned int *order = cfa_coef_order[prev->params.cfa_order];
256 const struct omap3isp_prev_cfa *cfa = ¶ms->cfa;
257 struct isp_device *isp = to_isp_device(prev);
258 unsigned int i;
259 unsigned int j;
260
261 isp_reg_writel(isp,
262 (cfa->gradthrs_vert << ISPPRV_CFA_GRADTH_VER_SHIFT) |
263 (cfa->gradthrs_horz << ISPPRV_CFA_GRADTH_HOR_SHIFT),
264 OMAP3_ISP_IOMEM_PREV, ISPPRV_CFA);
265
266 isp_reg_writel(isp, ISPPRV_CFA_TABLE_ADDR,
267 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
268
269 for (i = 0; i < 4; ++i) {
270 const __u32 *block = cfa->table[order[i]];
271
272 for (j = 0; j < OMAP3ISP_PREV_CFA_BLK_SIZE; ++j)
273 isp_reg_writel(isp, block[j], OMAP3_ISP_IOMEM_PREV,
274 ISPPRV_SET_TBL_DATA);
275 }
276}
277
278
279
280
281static void
282preview_config_chroma_suppression(struct isp_prev_device *prev,
283 const struct prev_params *params)
284{
285 struct isp_device *isp = to_isp_device(prev);
286 const struct omap3isp_prev_csup *cs = ¶ms->csup;
287
288 isp_reg_writel(isp,
289 cs->gain | (cs->thres << ISPPRV_CSUP_THRES_SHIFT) |
290 (cs->hypf_en << ISPPRV_CSUP_HPYF_SHIFT),
291 OMAP3_ISP_IOMEM_PREV, ISPPRV_CSUP);
292}
293
294
295
296
297static void
298preview_enable_chroma_suppression(struct isp_prev_device *prev, bool enable)
299{
300 struct isp_device *isp = to_isp_device(prev);
301
302 if (enable)
303 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
304 ISPPRV_PCR_SUPEN);
305 else
306 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
307 ISPPRV_PCR_SUPEN);
308}
309
310
311
312
313
314
315static void
316preview_config_whitebalance(struct isp_prev_device *prev,
317 const struct prev_params *params)
318{
319 struct isp_device *isp = to_isp_device(prev);
320 const struct omap3isp_prev_wbal *wbal = ¶ms->wbal;
321 u32 val;
322
323 isp_reg_writel(isp, wbal->dgain, OMAP3_ISP_IOMEM_PREV, ISPPRV_WB_DGAIN);
324
325 val = wbal->coef0 << ISPPRV_WBGAIN_COEF0_SHIFT;
326 val |= wbal->coef1 << ISPPRV_WBGAIN_COEF1_SHIFT;
327 val |= wbal->coef2 << ISPPRV_WBGAIN_COEF2_SHIFT;
328 val |= wbal->coef3 << ISPPRV_WBGAIN_COEF3_SHIFT;
329 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_WBGAIN);
330
331 isp_reg_writel(isp,
332 ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N0_0_SHIFT |
333 ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N0_1_SHIFT |
334 ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N0_2_SHIFT |
335 ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N0_3_SHIFT |
336 ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N1_0_SHIFT |
337 ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N1_1_SHIFT |
338 ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N1_2_SHIFT |
339 ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N1_3_SHIFT |
340 ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N2_0_SHIFT |
341 ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N2_1_SHIFT |
342 ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N2_2_SHIFT |
343 ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N2_3_SHIFT |
344 ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N3_0_SHIFT |
345 ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N3_1_SHIFT |
346 ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N3_2_SHIFT |
347 ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N3_3_SHIFT,
348 OMAP3_ISP_IOMEM_PREV, ISPPRV_WBSEL);
349}
350
351
352
353
354static void
355preview_config_blkadj(struct isp_prev_device *prev,
356 const struct prev_params *params)
357{
358 struct isp_device *isp = to_isp_device(prev);
359 const struct omap3isp_prev_blkadj *blkadj = ¶ms->blkadj;
360
361 isp_reg_writel(isp, (blkadj->blue << ISPPRV_BLKADJOFF_B_SHIFT) |
362 (blkadj->green << ISPPRV_BLKADJOFF_G_SHIFT) |
363 (blkadj->red << ISPPRV_BLKADJOFF_R_SHIFT),
364 OMAP3_ISP_IOMEM_PREV, ISPPRV_BLKADJOFF);
365}
366
367
368
369
370static void
371preview_config_rgb_blending(struct isp_prev_device *prev,
372 const struct prev_params *params)
373{
374 struct isp_device *isp = to_isp_device(prev);
375 const struct omap3isp_prev_rgbtorgb *rgbrgb = ¶ms->rgb2rgb;
376 u32 val;
377
378 val = (rgbrgb->matrix[0][0] & 0xfff) << ISPPRV_RGB_MAT1_MTX_RR_SHIFT;
379 val |= (rgbrgb->matrix[0][1] & 0xfff) << ISPPRV_RGB_MAT1_MTX_GR_SHIFT;
380 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT1);
381
382 val = (rgbrgb->matrix[0][2] & 0xfff) << ISPPRV_RGB_MAT2_MTX_BR_SHIFT;
383 val |= (rgbrgb->matrix[1][0] & 0xfff) << ISPPRV_RGB_MAT2_MTX_RG_SHIFT;
384 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT2);
385
386 val = (rgbrgb->matrix[1][1] & 0xfff) << ISPPRV_RGB_MAT3_MTX_GG_SHIFT;
387 val |= (rgbrgb->matrix[1][2] & 0xfff) << ISPPRV_RGB_MAT3_MTX_BG_SHIFT;
388 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT3);
389
390 val = (rgbrgb->matrix[2][0] & 0xfff) << ISPPRV_RGB_MAT4_MTX_RB_SHIFT;
391 val |= (rgbrgb->matrix[2][1] & 0xfff) << ISPPRV_RGB_MAT4_MTX_GB_SHIFT;
392 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT4);
393
394 val = (rgbrgb->matrix[2][2] & 0xfff) << ISPPRV_RGB_MAT5_MTX_BB_SHIFT;
395 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT5);
396
397 val = (rgbrgb->offset[0] & 0x3ff) << ISPPRV_RGB_OFF1_MTX_OFFR_SHIFT;
398 val |= (rgbrgb->offset[1] & 0x3ff) << ISPPRV_RGB_OFF1_MTX_OFFG_SHIFT;
399 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF1);
400
401 val = (rgbrgb->offset[2] & 0x3ff) << ISPPRV_RGB_OFF2_MTX_OFFB_SHIFT;
402 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF2);
403}
404
405
406
407
408static void
409preview_config_csc(struct isp_prev_device *prev,
410 const struct prev_params *params)
411{
412 struct isp_device *isp = to_isp_device(prev);
413 const struct omap3isp_prev_csc *csc = ¶ms->csc;
414 u32 val;
415
416 val = (csc->matrix[0][0] & 0x3ff) << ISPPRV_CSC0_RY_SHIFT;
417 val |= (csc->matrix[0][1] & 0x3ff) << ISPPRV_CSC0_GY_SHIFT;
418 val |= (csc->matrix[0][2] & 0x3ff) << ISPPRV_CSC0_BY_SHIFT;
419 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC0);
420
421 val = (csc->matrix[1][0] & 0x3ff) << ISPPRV_CSC1_RCB_SHIFT;
422 val |= (csc->matrix[1][1] & 0x3ff) << ISPPRV_CSC1_GCB_SHIFT;
423 val |= (csc->matrix[1][2] & 0x3ff) << ISPPRV_CSC1_BCB_SHIFT;
424 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC1);
425
426 val = (csc->matrix[2][0] & 0x3ff) << ISPPRV_CSC2_RCR_SHIFT;
427 val |= (csc->matrix[2][1] & 0x3ff) << ISPPRV_CSC2_GCR_SHIFT;
428 val |= (csc->matrix[2][2] & 0x3ff) << ISPPRV_CSC2_BCR_SHIFT;
429 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC2);
430
431 val = (csc->offset[0] & 0xff) << ISPPRV_CSC_OFFSET_Y_SHIFT;
432 val |= (csc->offset[1] & 0xff) << ISPPRV_CSC_OFFSET_CB_SHIFT;
433 val |= (csc->offset[2] & 0xff) << ISPPRV_CSC_OFFSET_CR_SHIFT;
434 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC_OFFSET);
435}
436
437
438
439
440static void
441preview_config_yc_range(struct isp_prev_device *prev,
442 const struct prev_params *params)
443{
444 struct isp_device *isp = to_isp_device(prev);
445 const struct omap3isp_prev_yclimit *yc = ¶ms->yclimit;
446
447 isp_reg_writel(isp,
448 yc->maxC << ISPPRV_SETUP_YC_MAXC_SHIFT |
449 yc->maxY << ISPPRV_SETUP_YC_MAXY_SHIFT |
450 yc->minC << ISPPRV_SETUP_YC_MINC_SHIFT |
451 yc->minY << ISPPRV_SETUP_YC_MINY_SHIFT,
452 OMAP3_ISP_IOMEM_PREV, ISPPRV_SETUP_YC);
453}
454
455
456
457
458static void
459preview_config_dcor(struct isp_prev_device *prev,
460 const struct prev_params *params)
461{
462 struct isp_device *isp = to_isp_device(prev);
463 const struct omap3isp_prev_dcor *dcor = ¶ms->dcor;
464
465 isp_reg_writel(isp, dcor->detect_correct[0],
466 OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR0);
467 isp_reg_writel(isp, dcor->detect_correct[1],
468 OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR1);
469 isp_reg_writel(isp, dcor->detect_correct[2],
470 OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR2);
471 isp_reg_writel(isp, dcor->detect_correct[3],
472 OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR3);
473 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
474 ISPPRV_PCR_DCCOUP,
475 dcor->couplet_mode_en ? ISPPRV_PCR_DCCOUP : 0);
476}
477
478
479
480
481static void preview_enable_dcor(struct isp_prev_device *prev, bool enable)
482{
483 struct isp_device *isp = to_isp_device(prev);
484
485 if (enable)
486 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
487 ISPPRV_PCR_DCOREN);
488 else
489 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
490 ISPPRV_PCR_DCOREN);
491}
492
493
494
495
496static void
497preview_enable_drkframe_capture(struct isp_prev_device *prev, bool enable)
498{
499 struct isp_device *isp = to_isp_device(prev);
500
501 if (enable)
502 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
503 ISPPRV_PCR_DRKFCAP);
504 else
505 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
506 ISPPRV_PCR_DRKFCAP);
507}
508
509
510
511
512static void preview_enable_drkframe(struct isp_prev_device *prev, bool enable)
513{
514 struct isp_device *isp = to_isp_device(prev);
515
516 if (enable)
517 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
518 ISPPRV_PCR_DRKFEN);
519 else
520 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
521 ISPPRV_PCR_DRKFEN);
522}
523
524
525
526
527static void
528preview_config_noisefilter(struct isp_prev_device *prev,
529 const struct prev_params *params)
530{
531 struct isp_device *isp = to_isp_device(prev);
532 const struct omap3isp_prev_nf *nf = ¶ms->nf;
533 unsigned int i;
534
535 isp_reg_writel(isp, nf->spread, OMAP3_ISP_IOMEM_PREV, ISPPRV_NF);
536 isp_reg_writel(isp, ISPPRV_NF_TABLE_ADDR,
537 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
538 for (i = 0; i < OMAP3ISP_PREV_NF_TBL_SIZE; i++) {
539 isp_reg_writel(isp, nf->table[i],
540 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
541 }
542}
543
544
545
546
547static void
548preview_enable_noisefilter(struct isp_prev_device *prev, bool enable)
549{
550 struct isp_device *isp = to_isp_device(prev);
551
552 if (enable)
553 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
554 ISPPRV_PCR_NFEN);
555 else
556 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
557 ISPPRV_PCR_NFEN);
558}
559
560
561
562
563static void
564preview_config_gammacorrn(struct isp_prev_device *prev,
565 const struct prev_params *params)
566{
567 struct isp_device *isp = to_isp_device(prev);
568 const struct omap3isp_prev_gtables *gt = ¶ms->gamma;
569 unsigned int i;
570
571 isp_reg_writel(isp, ISPPRV_REDGAMMA_TABLE_ADDR,
572 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
573 for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++)
574 isp_reg_writel(isp, gt->red[i], OMAP3_ISP_IOMEM_PREV,
575 ISPPRV_SET_TBL_DATA);
576
577 isp_reg_writel(isp, ISPPRV_GREENGAMMA_TABLE_ADDR,
578 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
579 for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++)
580 isp_reg_writel(isp, gt->green[i], OMAP3_ISP_IOMEM_PREV,
581 ISPPRV_SET_TBL_DATA);
582
583 isp_reg_writel(isp, ISPPRV_BLUEGAMMA_TABLE_ADDR,
584 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
585 for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++)
586 isp_reg_writel(isp, gt->blue[i], OMAP3_ISP_IOMEM_PREV,
587 ISPPRV_SET_TBL_DATA);
588}
589
590
591
592
593
594
595
596static void
597preview_enable_gammacorrn(struct isp_prev_device *prev, bool enable)
598{
599 struct isp_device *isp = to_isp_device(prev);
600
601 if (enable)
602 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
603 ISPPRV_PCR_GAMMA_BYPASS);
604 else
605 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
606 ISPPRV_PCR_GAMMA_BYPASS);
607}
608
609
610
611
612
613
614static void
615preview_config_contrast(struct isp_prev_device *prev,
616 const struct prev_params *params)
617{
618 struct isp_device *isp = to_isp_device(prev);
619
620 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT,
621 0xff << ISPPRV_CNT_BRT_CNT_SHIFT,
622 params->contrast << ISPPRV_CNT_BRT_CNT_SHIFT);
623}
624
625
626
627
628static void
629preview_config_brightness(struct isp_prev_device *prev,
630 const struct prev_params *params)
631{
632 struct isp_device *isp = to_isp_device(prev);
633
634 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT,
635 0xff << ISPPRV_CNT_BRT_BRT_SHIFT,
636 params->brightness << ISPPRV_CNT_BRT_BRT_SHIFT);
637}
638
639
640
641
642
643
644
645static void
646preview_update_contrast(struct isp_prev_device *prev, u8 contrast)
647{
648 struct prev_params *params;
649 unsigned long flags;
650
651 spin_lock_irqsave(&prev->params.lock, flags);
652 params = (prev->params.active & OMAP3ISP_PREV_CONTRAST)
653 ? &prev->params.params[0] : &prev->params.params[1];
654
655 if (params->contrast != (contrast * ISPPRV_CONTRAST_UNITS)) {
656 params->contrast = contrast * ISPPRV_CONTRAST_UNITS;
657 params->update |= OMAP3ISP_PREV_CONTRAST;
658 }
659 spin_unlock_irqrestore(&prev->params.lock, flags);
660}
661
662
663
664
665
666
667static void
668preview_update_brightness(struct isp_prev_device *prev, u8 brightness)
669{
670 struct prev_params *params;
671 unsigned long flags;
672
673 spin_lock_irqsave(&prev->params.lock, flags);
674 params = (prev->params.active & OMAP3ISP_PREV_BRIGHTNESS)
675 ? &prev->params.params[0] : &prev->params.params[1];
676
677 if (params->brightness != (brightness * ISPPRV_BRIGHT_UNITS)) {
678 params->brightness = brightness * ISPPRV_BRIGHT_UNITS;
679 params->update |= OMAP3ISP_PREV_BRIGHTNESS;
680 }
681 spin_unlock_irqrestore(&prev->params.lock, flags);
682}
683
684static u32
685preview_params_lock(struct isp_prev_device *prev, u32 update, bool shadow)
686{
687 u32 active = prev->params.active;
688
689 if (shadow) {
690
691 prev->params.params[0].busy |= ~active & update;
692 prev->params.params[1].busy |= active & update;
693 } else {
694
695 update = (prev->params.params[0].update & active)
696 | (prev->params.params[1].update & ~active);
697
698 prev->params.params[0].busy |= active & update;
699 prev->params.params[1].busy |= ~active & update;
700 }
701
702 return update;
703}
704
705static void
706preview_params_unlock(struct isp_prev_device *prev, u32 update, bool shadow)
707{
708 u32 active = prev->params.active;
709
710 if (shadow) {
711
712
713
714 prev->params.params[0].update |= (~active & update);
715 prev->params.params[1].update |= (active & update);
716 prev->params.params[0].busy &= active;
717 prev->params.params[1].busy &= ~active;
718 } else {
719
720
721
722 prev->params.params[0].update &= ~(active & update);
723 prev->params.params[1].update &= ~(~active & update);
724 prev->params.params[0].busy &= ~active;
725 prev->params.params[1].busy &= active;
726 }
727}
728
729static void preview_params_switch(struct isp_prev_device *prev)
730{
731 u32 to_switch;
732
733
734
735
736
737 to_switch = (prev->params.params[0].update & ~prev->params.active)
738 | (prev->params.params[1].update & prev->params.active);
739 to_switch &= ~(prev->params.params[0].busy |
740 prev->params.params[1].busy);
741 if (to_switch == 0)
742 return;
743
744 prev->params.active ^= to_switch;
745
746
747
748
749 prev->params.params[0].update &= ~(~prev->params.active & to_switch);
750 prev->params.params[1].update &= ~(prev->params.active & to_switch);
751}
752
753
754struct preview_update {
755 void (*config)(struct isp_prev_device *, const struct prev_params *);
756 void (*enable)(struct isp_prev_device *, bool);
757 unsigned int param_offset;
758 unsigned int param_size;
759 unsigned int config_offset;
760 bool skip;
761};
762
763
764static const struct preview_update update_attrs[] = {
765 {
766 preview_config_luma_enhancement,
767 preview_enable_luma_enhancement,
768 offsetof(struct prev_params, luma),
769 FIELD_SIZEOF(struct prev_params, luma),
770 offsetof(struct omap3isp_prev_update_config, luma),
771 }, {
772 NULL,
773 preview_enable_invalaw,
774 }, {
775 preview_config_hmed,
776 preview_enable_hmed,
777 offsetof(struct prev_params, hmed),
778 FIELD_SIZEOF(struct prev_params, hmed),
779 offsetof(struct omap3isp_prev_update_config, hmed),
780 }, {
781 preview_config_cfa,
782 NULL,
783 offsetof(struct prev_params, cfa),
784 FIELD_SIZEOF(struct prev_params, cfa),
785 offsetof(struct omap3isp_prev_update_config, cfa),
786 }, {
787 preview_config_chroma_suppression,
788 preview_enable_chroma_suppression,
789 offsetof(struct prev_params, csup),
790 FIELD_SIZEOF(struct prev_params, csup),
791 offsetof(struct omap3isp_prev_update_config, csup),
792 }, {
793 preview_config_whitebalance,
794 NULL,
795 offsetof(struct prev_params, wbal),
796 FIELD_SIZEOF(struct prev_params, wbal),
797 offsetof(struct omap3isp_prev_update_config, wbal),
798 }, {
799 preview_config_blkadj,
800 NULL,
801 offsetof(struct prev_params, blkadj),
802 FIELD_SIZEOF(struct prev_params, blkadj),
803 offsetof(struct omap3isp_prev_update_config, blkadj),
804 }, {
805 preview_config_rgb_blending,
806 NULL,
807 offsetof(struct prev_params, rgb2rgb),
808 FIELD_SIZEOF(struct prev_params, rgb2rgb),
809 offsetof(struct omap3isp_prev_update_config, rgb2rgb),
810 }, {
811 preview_config_csc,
812 NULL,
813 offsetof(struct prev_params, csc),
814 FIELD_SIZEOF(struct prev_params, csc),
815 offsetof(struct omap3isp_prev_update_config, csc),
816 }, {
817 preview_config_yc_range,
818 NULL,
819 offsetof(struct prev_params, yclimit),
820 FIELD_SIZEOF(struct prev_params, yclimit),
821 offsetof(struct omap3isp_prev_update_config, yclimit),
822 }, {
823 preview_config_dcor,
824 preview_enable_dcor,
825 offsetof(struct prev_params, dcor),
826 FIELD_SIZEOF(struct prev_params, dcor),
827 offsetof(struct omap3isp_prev_update_config, dcor),
828 }, {
829 NULL,
830 NULL,
831 }, {
832 NULL,
833 preview_enable_drkframe_capture,
834 }, {
835 NULL,
836 preview_enable_drkframe,
837 }, {
838 NULL,
839 preview_enable_drkframe,
840 }, {
841 preview_config_noisefilter,
842 preview_enable_noisefilter,
843 offsetof(struct prev_params, nf),
844 FIELD_SIZEOF(struct prev_params, nf),
845 offsetof(struct omap3isp_prev_update_config, nf),
846 }, {
847 preview_config_gammacorrn,
848 preview_enable_gammacorrn,
849 offsetof(struct prev_params, gamma),
850 FIELD_SIZEOF(struct prev_params, gamma),
851 offsetof(struct omap3isp_prev_update_config, gamma),
852 }, {
853 preview_config_contrast,
854 NULL,
855 0, 0, 0, true,
856 }, {
857 preview_config_brightness,
858 NULL,
859 0, 0, 0, true,
860 },
861};
862
863
864
865
866
867
868
869
870
871
872static int preview_config(struct isp_prev_device *prev,
873 struct omap3isp_prev_update_config *cfg)
874{
875 unsigned long flags;
876 unsigned int i;
877 int rval = 0;
878 u32 update;
879 u32 active;
880
881 if (cfg->update == 0)
882 return 0;
883
884
885 spin_lock_irqsave(&prev->params.lock, flags);
886 preview_params_lock(prev, cfg->update, true);
887 active = prev->params.active;
888 spin_unlock_irqrestore(&prev->params.lock, flags);
889
890 update = 0;
891
892 for (i = 0; i < ARRAY_SIZE(update_attrs); i++) {
893 const struct preview_update *attr = &update_attrs[i];
894 struct prev_params *params;
895 unsigned int bit = 1 << i;
896
897 if (attr->skip || !(cfg->update & bit))
898 continue;
899
900 params = &prev->params.params[!!(active & bit)];
901
902 if (cfg->flag & bit) {
903 void __user *from = *(void * __user *)
904 ((void *)cfg + attr->config_offset);
905 void *to = (void *)params + attr->param_offset;
906 size_t size = attr->param_size;
907
908 if (to && from && size) {
909 if (copy_from_user(to, from, size)) {
910 rval = -EFAULT;
911 break;
912 }
913 }
914 params->features |= bit;
915 } else {
916 params->features &= ~bit;
917 }
918
919 update |= bit;
920 }
921
922 spin_lock_irqsave(&prev->params.lock, flags);
923 preview_params_unlock(prev, update, true);
924 preview_params_switch(prev);
925 spin_unlock_irqrestore(&prev->params.lock, flags);
926
927 return rval;
928}
929
930
931
932
933
934
935
936
937
938static void preview_setup_hw(struct isp_prev_device *prev, u32 update,
939 u32 active)
940{
941 unsigned int i;
942 u32 features;
943
944 if (update == 0)
945 return;
946
947 features = (prev->params.params[0].features & active)
948 | (prev->params.params[1].features & ~active);
949
950 for (i = 0; i < ARRAY_SIZE(update_attrs); i++) {
951 const struct preview_update *attr = &update_attrs[i];
952 struct prev_params *params;
953 unsigned int bit = 1 << i;
954
955 if (!(update & bit))
956 continue;
957
958 params = &prev->params.params[!(active & bit)];
959
960 if (params->features & bit) {
961 if (attr->config)
962 attr->config(prev, params);
963 if (attr->enable)
964 attr->enable(prev, true);
965 } else {
966 if (attr->enable)
967 attr->enable(prev, false);
968 }
969 }
970}
971
972
973
974
975
976static void
977preview_config_ycpos(struct isp_prev_device *prev,
978 enum v4l2_mbus_pixelcode pixelcode)
979{
980 struct isp_device *isp = to_isp_device(prev);
981 enum preview_ycpos_mode mode;
982
983 switch (pixelcode) {
984 case V4L2_MBUS_FMT_YUYV8_1X16:
985 mode = YCPOS_CrYCbY;
986 break;
987 case V4L2_MBUS_FMT_UYVY8_1X16:
988 mode = YCPOS_YCrYCb;
989 break;
990 default:
991 return;
992 }
993
994 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
995 ISPPRV_PCR_YCPOS_CrYCbY,
996 mode << ISPPRV_PCR_YCPOS_SHIFT);
997}
998
999
1000
1001
1002
1003static void preview_config_averager(struct isp_prev_device *prev, u8 average)
1004{
1005 struct isp_device *isp = to_isp_device(prev);
1006
1007 isp_reg_writel(isp, ISPPRV_AVE_EVENDIST_2 << ISPPRV_AVE_EVENDIST_SHIFT |
1008 ISPPRV_AVE_ODDDIST_2 << ISPPRV_AVE_ODDDIST_SHIFT |
1009 average, OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE);
1010}
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026static void preview_config_input_format(struct isp_prev_device *prev,
1027 const struct isp_format_info *info)
1028{
1029 struct isp_device *isp = to_isp_device(prev);
1030 struct prev_params *params;
1031
1032 if (info->width == 8)
1033 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1034 ISPPRV_PCR_WIDTH);
1035 else
1036 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1037 ISPPRV_PCR_WIDTH);
1038
1039 switch (info->flavor) {
1040 case V4L2_MBUS_FMT_SGRBG8_1X8:
1041 prev->params.cfa_order = 0;
1042 break;
1043 case V4L2_MBUS_FMT_SRGGB8_1X8:
1044 prev->params.cfa_order = 1;
1045 break;
1046 case V4L2_MBUS_FMT_SBGGR8_1X8:
1047 prev->params.cfa_order = 2;
1048 break;
1049 case V4L2_MBUS_FMT_SGBRG8_1X8:
1050 prev->params.cfa_order = 3;
1051 break;
1052 default:
1053
1054 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1055 ISPPRV_PCR_CFAEN);
1056 return;
1057 }
1058
1059 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_CFAEN);
1060 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1061 ISPPRV_PCR_CFAFMT_MASK, ISPPRV_PCR_CFAFMT_BAYER);
1062
1063 params = (prev->params.active & OMAP3ISP_PREV_CFA)
1064 ? &prev->params.params[0] : &prev->params.params[1];
1065
1066 preview_config_cfa(prev, params);
1067}
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080static void preview_config_input_size(struct isp_prev_device *prev, u32 active)
1081{
1082 struct isp_device *isp = to_isp_device(prev);
1083 unsigned int sph = prev->crop.left;
1084 unsigned int eph = prev->crop.left + prev->crop.width - 1;
1085 unsigned int slv = prev->crop.top;
1086 unsigned int elv = prev->crop.top + prev->crop.height - 1;
1087 u32 features;
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->isp_addr);
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->isp_addr);
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->isp_addr);
1571
1572 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1573 preview_set_outaddr(prev, buffer->isp_addr);
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 pads[PREV_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
2288
2289 me->ops = &preview_media_ops;
2290 ret = media_entity_init(me, PREV_PADS_NUM, pads, 0);
2291 if (ret < 0)
2292 return ret;
2293
2294 preview_init_formats(sd, NULL);
2295
2296
2297
2298
2299
2300 prev->video_in.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
2301 prev->video_in.ops = &preview_video_ops;
2302 prev->video_in.isp = to_isp_device(prev);
2303 prev->video_in.capture_mem = PAGE_ALIGN(4096 * 4096) * 2 * 3;
2304 prev->video_in.bpl_alignment = 64;
2305 prev->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2306 prev->video_out.ops = &preview_video_ops;
2307 prev->video_out.isp = to_isp_device(prev);
2308 prev->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 2 * 3;
2309 prev->video_out.bpl_alignment = 32;
2310
2311 ret = omap3isp_video_init(&prev->video_in, "preview");
2312 if (ret < 0)
2313 goto error_video_in;
2314
2315 ret = omap3isp_video_init(&prev->video_out, "preview");
2316 if (ret < 0)
2317 goto error_video_out;
2318
2319
2320 ret = media_entity_create_link(&prev->video_in.video.entity, 0,
2321 &prev->subdev.entity, PREV_PAD_SINK, 0);
2322 if (ret < 0)
2323 goto error_link;
2324
2325 ret = media_entity_create_link(&prev->subdev.entity, PREV_PAD_SOURCE,
2326 &prev->video_out.video.entity, 0, 0);
2327 if (ret < 0)
2328 goto error_link;
2329
2330 return 0;
2331
2332error_link:
2333 omap3isp_video_cleanup(&prev->video_out);
2334error_video_out:
2335 omap3isp_video_cleanup(&prev->video_in);
2336error_video_in:
2337 media_entity_cleanup(&prev->subdev.entity);
2338 return ret;
2339}
2340
2341
2342
2343
2344
2345
2346int omap3isp_preview_init(struct isp_device *isp)
2347{
2348 struct isp_prev_device *prev = &isp->isp_prev;
2349
2350 init_waitqueue_head(&prev->wait);
2351
2352 preview_init_params(prev);
2353
2354 return preview_init_entities(prev);
2355}
2356
2357void omap3isp_preview_cleanup(struct isp_device *isp)
2358{
2359 struct isp_prev_device *prev = &isp->isp_prev;
2360
2361 v4l2_ctrl_handler_free(&prev->ctrls);
2362 omap3isp_video_cleanup(&prev->video_in);
2363 omap3isp_video_cleanup(&prev->video_out);
2364 media_entity_cleanup(&prev->subdev.entity);
2365}
2366