1
2
3
4#include <linux/uaccess.h>
5#include <linux/interrupt.h>
6#include <mach/irqs.h>
7#include "msm_vfe8x_proc.h"
8
9#define ON 1
10#define OFF 0
11
12struct mutex vfe_lock;
13static void *vfe_syncdata;
14
15static int vfe_enable(struct camera_enable_cmd *enable)
16{
17 int rc = 0;
18 return rc;
19}
20
21static int vfe_disable(struct camera_enable_cmd *enable,
22 struct platform_device *dev)
23{
24 int rc = 0;
25
26 vfe_stop();
27
28 msm_camio_disable(dev);
29 return rc;
30}
31
32static void vfe_release(struct platform_device *dev)
33{
34 msm_camio_disable(dev);
35 vfe_cmd_release(dev);
36
37 mutex_lock(&vfe_lock);
38 vfe_syncdata = NULL;
39 mutex_unlock(&vfe_lock);
40}
41
42static void vfe_config_axi(int mode,
43 struct axidata *ad, struct vfe_cmd_axi_output_config *ao)
44{
45 struct msm_pmem_region *regptr;
46 int i, j;
47 uint32_t *p1, *p2;
48
49 if (mode == OUTPUT_1 || mode == OUTPUT_1_AND_2) {
50 regptr = ad->region;
51 for (i = 0;
52 i < ad->bufnum1; i++) {
53
54 p1 = &(ao->output1.outputY.outFragments[i][0]);
55 p2 = &(ao->output1.outputCbcr.outFragments[i][0]);
56
57 for (j = 0;
58 j < ao->output1.fragmentCount; j++) {
59
60 *p1 = regptr->paddr + regptr->y_off;
61 p1++;
62
63 *p2 = regptr->paddr + regptr->cbcr_off;
64 p2++;
65 }
66 regptr++;
67 }
68 }
69
70 if (mode == OUTPUT_2 || mode == OUTPUT_1_AND_2) {
71
72 regptr = &(ad->region[ad->bufnum1]);
73 CDBG("bufnum2 = %d\n", ad->bufnum2);
74
75 for (i = 0;
76 i < ad->bufnum2; i++) {
77
78 p1 = &(ao->output2.outputY.outFragments[i][0]);
79 p2 = &(ao->output2.outputCbcr.outFragments[i][0]);
80
81 CDBG("config_axi: O2, phy = 0x%lx, y_off = %d, cbcr_off = %d\n",
82 regptr->paddr, regptr->y_off, regptr->cbcr_off);
83
84 for (j = 0;
85 j < ao->output2.fragmentCount; j++) {
86
87 *p1 = regptr->paddr + regptr->y_off;
88 CDBG("vfe_config_axi: p1 = 0x%x\n", *p1);
89 p1++;
90
91 *p2 = regptr->paddr + regptr->cbcr_off;
92 CDBG("vfe_config_axi: p2 = 0x%x\n", *p2);
93 p2++;
94 }
95 regptr++;
96 }
97 }
98}
99
100static int vfe_proc_general(struct msm_vfe_command_8k *cmd)
101{
102 int rc = 0;
103
104 CDBG("vfe_proc_general: cmdID = %d\n", cmd->id);
105
106 switch (cmd->id) {
107 case VFE_CMD_ID_RESET:
108 msm_camio_vfe_blk_reset();
109 msm_camio_camif_pad_reg_reset_2();
110 vfe_reset();
111 break;
112
113 case VFE_CMD_ID_START: {
114 struct vfe_cmd_start start;
115 if (copy_from_user(&start,
116 (void __user *) cmd->value, cmd->length))
117 rc = -EFAULT;
118
119
120 msm_camio_camif_pad_reg_reset();
121 vfe_start(&start);
122 }
123 break;
124
125 case VFE_CMD_ID_CAMIF_CONFIG: {
126 struct vfe_cmd_camif_config camif;
127 if (copy_from_user(&camif,
128 (void __user *) cmd->value, cmd->length))
129 rc = -EFAULT;
130
131 vfe_camif_config(&camif);
132 }
133 break;
134
135 case VFE_CMD_ID_BLACK_LEVEL_CONFIG: {
136 struct vfe_cmd_black_level_config bl;
137 if (copy_from_user(&bl,
138 (void __user *) cmd->value, cmd->length))
139 rc = -EFAULT;
140
141 vfe_black_level_config(&bl);
142 }
143 break;
144
145 case VFE_CMD_ID_ROLL_OFF_CONFIG: {
146 struct vfe_cmd_roll_off_config rolloff;
147 if (copy_from_user(&rolloff,
148 (void __user *) cmd->value, cmd->length))
149 rc = -EFAULT;
150
151 vfe_roll_off_config(&rolloff);
152 }
153 break;
154
155 case VFE_CMD_ID_DEMUX_CHANNEL_GAIN_CONFIG: {
156 struct vfe_cmd_demux_channel_gain_config demuxc;
157 if (copy_from_user(&demuxc,
158 (void __user *) cmd->value, cmd->length))
159 rc = -EFAULT;
160
161
162 vfe_demux_channel_gain_config(&demuxc);
163 }
164 break;
165
166 case VFE_CMD_ID_DEMOSAIC_CONFIG: {
167 struct vfe_cmd_demosaic_config demosaic;
168 if (copy_from_user(&demosaic,
169 (void __user *) cmd->value, cmd->length))
170 rc = -EFAULT;
171
172 vfe_demosaic_config(&demosaic);
173 }
174 break;
175
176 case VFE_CMD_ID_FOV_CROP_CONFIG:
177 case VFE_CMD_ID_FOV_CROP_UPDATE: {
178 struct vfe_cmd_fov_crop_config fov;
179 if (copy_from_user(&fov,
180 (void __user *) cmd->value, cmd->length))
181 rc = -EFAULT;
182
183 vfe_fov_crop_config(&fov);
184 }
185 break;
186
187 case VFE_CMD_ID_MAIN_SCALER_CONFIG:
188 case VFE_CMD_ID_MAIN_SCALER_UPDATE: {
189 struct vfe_cmd_main_scaler_config mainds;
190 if (copy_from_user(&mainds,
191 (void __user *) cmd->value, cmd->length))
192 rc = -EFAULT;
193
194 vfe_main_scaler_config(&mainds);
195 }
196 break;
197
198 case VFE_CMD_ID_WHITE_BALANCE_CONFIG:
199 case VFE_CMD_ID_WHITE_BALANCE_UPDATE: {
200 struct vfe_cmd_white_balance_config wb;
201 if (copy_from_user(&wb,
202 (void __user *) cmd->value, cmd->length))
203 rc = -EFAULT;
204
205 vfe_white_balance_config(&wb);
206 }
207 break;
208
209 case VFE_CMD_ID_COLOR_CORRECTION_CONFIG:
210 case VFE_CMD_ID_COLOR_CORRECTION_UPDATE: {
211 struct vfe_cmd_color_correction_config cc;
212 if (copy_from_user(&cc,
213 (void __user *) cmd->value, cmd->length))
214 rc = -EFAULT;
215
216 vfe_color_correction_config(&cc);
217 }
218 break;
219
220 case VFE_CMD_ID_LA_CONFIG: {
221 struct vfe_cmd_la_config la;
222 if (copy_from_user(&la,
223 (void __user *) cmd->value, cmd->length))
224 rc = -EFAULT;
225
226 vfe_la_config(&la);
227 }
228 break;
229
230 case VFE_CMD_ID_RGB_GAMMA_CONFIG: {
231 struct vfe_cmd_rgb_gamma_config rgb;
232 if (copy_from_user(&rgb,
233 (void __user *) cmd->value, cmd->length))
234 rc = -EFAULT;
235
236 rc = vfe_rgb_gamma_config(&rgb);
237 }
238 break;
239
240 case VFE_CMD_ID_CHROMA_ENHAN_CONFIG:
241 case VFE_CMD_ID_CHROMA_ENHAN_UPDATE: {
242 struct vfe_cmd_chroma_enhan_config chrom;
243 if (copy_from_user(&chrom,
244 (void __user *) cmd->value, cmd->length))
245 rc = -EFAULT;
246
247 vfe_chroma_enhan_config(&chrom);
248 }
249 break;
250
251 case VFE_CMD_ID_CHROMA_SUPPRESSION_CONFIG:
252 case VFE_CMD_ID_CHROMA_SUPPRESSION_UPDATE: {
253 struct vfe_cmd_chroma_suppression_config chromsup;
254 if (copy_from_user(&chromsup,
255 (void __user *) cmd->value, cmd->length))
256 rc = -EFAULT;
257
258 vfe_chroma_sup_config(&chromsup);
259 }
260 break;
261
262 case VFE_CMD_ID_ASF_CONFIG: {
263 struct vfe_cmd_asf_config asf;
264 if (copy_from_user(&asf,
265 (void __user *) cmd->value, cmd->length))
266 rc = -EFAULT;
267
268 vfe_asf_config(&asf);
269 }
270 break;
271
272 case VFE_CMD_ID_SCALER2Y_CONFIG:
273 case VFE_CMD_ID_SCALER2Y_UPDATE: {
274 struct vfe_cmd_scaler2_config ds2y;
275 if (copy_from_user(&ds2y,
276 (void __user *) cmd->value, cmd->length))
277 rc = -EFAULT;
278
279 vfe_scaler2y_config(&ds2y);
280 }
281 break;
282
283 case VFE_CMD_ID_SCALER2CbCr_CONFIG:
284 case VFE_CMD_ID_SCALER2CbCr_UPDATE: {
285 struct vfe_cmd_scaler2_config ds2cbcr;
286 if (copy_from_user(&ds2cbcr,
287 (void __user *) cmd->value, cmd->length))
288 rc = -EFAULT;
289
290 vfe_scaler2cbcr_config(&ds2cbcr);
291 }
292 break;
293
294 case VFE_CMD_ID_CHROMA_SUBSAMPLE_CONFIG: {
295 struct vfe_cmd_chroma_subsample_config sub;
296 if (copy_from_user(&sub,
297 (void __user *) cmd->value, cmd->length))
298 rc = -EFAULT;
299
300 vfe_chroma_subsample_config(&sub);
301 }
302 break;
303
304 case VFE_CMD_ID_FRAME_SKIP_CONFIG: {
305 struct vfe_cmd_frame_skip_config fskip;
306 if (copy_from_user(&fskip,
307 (void __user *) cmd->value, cmd->length))
308 rc = -EFAULT;
309
310 vfe_frame_skip_config(&fskip);
311 }
312 break;
313
314 case VFE_CMD_ID_OUTPUT_CLAMP_CONFIG: {
315 struct vfe_cmd_output_clamp_config clamp;
316 if (copy_from_user(&clamp,
317 (void __user *) cmd->value, cmd->length))
318 rc = -EFAULT;
319
320 vfe_output_clamp_config(&clamp);
321 }
322 break;
323
324
325 case VFE_CMD_ID_BLACK_LEVEL_UPDATE: {
326 struct vfe_cmd_black_level_config blk;
327 if (copy_from_user(&blk,
328 (void __user *) cmd->value, cmd->length))
329 rc = -EFAULT;
330
331 vfe_black_level_update(&blk);
332 }
333 break;
334
335 case VFE_CMD_ID_DEMUX_CHANNEL_GAIN_UPDATE: {
336 struct vfe_cmd_demux_channel_gain_config dmu;
337 if (copy_from_user(&dmu,
338 (void __user *) cmd->value, cmd->length))
339 rc = -EFAULT;
340
341 vfe_demux_channel_gain_update(&dmu);
342 }
343 break;
344
345 case VFE_CMD_ID_DEMOSAIC_BPC_UPDATE: {
346 struct vfe_cmd_demosaic_bpc_update demo_bpc;
347 if (copy_from_user(&demo_bpc,
348 (void __user *) cmd->value, cmd->length))
349 rc = -EFAULT;
350
351 vfe_demosaic_bpc_update(&demo_bpc);
352 }
353 break;
354
355 case VFE_CMD_ID_DEMOSAIC_ABF_UPDATE: {
356 struct vfe_cmd_demosaic_abf_update demo_abf;
357 if (copy_from_user(&demo_abf,
358 (void __user *) cmd->value, cmd->length))
359 rc = -EFAULT;
360
361 vfe_demosaic_abf_update(&demo_abf);
362 }
363 break;
364
365 case VFE_CMD_ID_LA_UPDATE: {
366 struct vfe_cmd_la_config la;
367 if (copy_from_user(&la,
368 (void __user *) cmd->value, cmd->length))
369 rc = -EFAULT;
370
371 vfe_la_update(&la);
372 }
373 break;
374
375 case VFE_CMD_ID_RGB_GAMMA_UPDATE: {
376 struct vfe_cmd_rgb_gamma_config rgb;
377 if (copy_from_user(&rgb,
378 (void __user *) cmd->value, cmd->length))
379 rc = -EFAULT;
380
381 rc = vfe_rgb_gamma_update(&rgb);
382 }
383 break;
384
385 case VFE_CMD_ID_ASF_UPDATE: {
386 struct vfe_cmd_asf_update asf;
387 if (copy_from_user(&asf,
388 (void __user *) cmd->value, cmd->length))
389 rc = -EFAULT;
390
391 vfe_asf_update(&asf);
392 }
393 break;
394
395 case VFE_CMD_ID_FRAME_SKIP_UPDATE: {
396 struct vfe_cmd_frame_skip_update fskip;
397 if (copy_from_user(&fskip,
398 (void __user *) cmd->value, cmd->length))
399 rc = -EFAULT;
400
401 vfe_frame_skip_update(&fskip);
402 }
403 break;
404
405 case VFE_CMD_ID_CAMIF_FRAME_UPDATE: {
406 struct vfe_cmds_camif_frame fup;
407 if (copy_from_user(&fup,
408 (void __user *) cmd->value, cmd->length))
409 rc = -EFAULT;
410
411 vfe_camif_frame_update(&fup);
412 }
413 break;
414
415
416 case VFE_CMD_ID_STATS_AUTOFOCUS_UPDATE: {
417 struct vfe_cmd_stats_af_update afup;
418 if (copy_from_user(&afup,
419 (void __user *) cmd->value, cmd->length))
420 rc = -EFAULT;
421
422 vfe_stats_update_af(&afup);
423 }
424 break;
425
426 case VFE_CMD_ID_STATS_WB_EXP_UPDATE: {
427 struct vfe_cmd_stats_wb_exp_update wbexp;
428 if (copy_from_user(&wbexp,
429 (void __user *) cmd->value, cmd->length))
430 rc = -EFAULT;
431
432 vfe_stats_update_wb_exp(&wbexp);
433 }
434 break;
435
436
437 case VFE_CMD_ID_STOP:
438 vfe_stop();
439 break;
440
441 case VFE_CMD_ID_GET_HW_VERSION:
442 break;
443
444
445 case VFE_CMD_ID_STATS_SETTING: {
446 struct vfe_cmd_stats_setting stats;
447 if (copy_from_user(&stats,
448 (void __user *) cmd->value, cmd->length))
449 rc = -EFAULT;
450
451 vfe_stats_setting(&stats);
452 }
453 break;
454
455 case VFE_CMD_ID_STATS_AUTOFOCUS_START: {
456 struct vfe_cmd_stats_af_start af;
457 if (copy_from_user(&af,
458 (void __user *) cmd->value, cmd->length))
459 rc = -EFAULT;
460
461 vfe_stats_start_af(&af);
462 }
463 break;
464
465 case VFE_CMD_ID_STATS_AUTOFOCUS_STOP:
466 vfe_stats_af_stop();
467 break;
468
469 case VFE_CMD_ID_STATS_WB_EXP_START: {
470 struct vfe_cmd_stats_wb_exp_start awexp;
471 if (copy_from_user(&awexp,
472 (void __user *) cmd->value, cmd->length))
473 rc = -EFAULT;
474
475 vfe_stats_start_wb_exp(&awexp);
476 }
477 break;
478
479 case VFE_CMD_ID_STATS_WB_EXP_STOP:
480 vfe_stats_wb_exp_stop();
481 break;
482
483 case VFE_CMD_ID_ASYNC_TIMER_SETTING:
484 break;
485
486 case VFE_CMD_ID_UPDATE:
487 vfe_update();
488 break;
489
490
491 case VFE_CMD_ID_TEST_GEN_START:
492 break;
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512 default:
513 break;
514 }
515
516 return rc;
517}
518
519static int vfe_config(struct msm_vfe_cfg_cmd *cmd, void *data)
520{
521 struct msm_pmem_region *regptr;
522 struct msm_vfe_command_8k vfecmd;
523
524 uint32_t i;
525
526 void *cmd_data = NULL;
527 long rc = 0;
528
529 struct vfe_cmd_axi_output_config *axio = NULL;
530 struct vfe_cmd_stats_setting *scfg = NULL;
531
532 if (cmd->cmd_type != CMD_FRAME_BUF_RELEASE &&
533 cmd->cmd_type != CMD_STATS_BUF_RELEASE) {
534
535 if (copy_from_user(&vfecmd,
536 (void __user *)(cmd->value),
537 sizeof(struct msm_vfe_command_8k)))
538 return -EFAULT;
539 }
540
541 CDBG("vfe_config: cmdType = %d\n", cmd->cmd_type);
542
543 switch (cmd->cmd_type) {
544 case CMD_GENERAL:
545 rc = vfe_proc_general(&vfecmd);
546 break;
547
548 case CMD_STATS_ENABLE:
549 case CMD_STATS_AXI_CFG: {
550 struct axidata *axid;
551
552 axid = data;
553 if (!axid)
554 return -EFAULT;
555
556 scfg =
557 kmalloc(sizeof(struct vfe_cmd_stats_setting),
558 GFP_ATOMIC);
559 if (!scfg)
560 return -ENOMEM;
561
562 if (copy_from_user(scfg,
563 (void __user *)(vfecmd.value),
564 vfecmd.length)) {
565
566 kfree(scfg);
567 return -EFAULT;
568 }
569
570 regptr = axid->region;
571 if (axid->bufnum1 > 0) {
572 for (i = 0; i < axid->bufnum1; i++) {
573 scfg->awbBuffer[i] =
574 (uint32_t)(regptr->paddr);
575 regptr++;
576 }
577 }
578
579 if (axid->bufnum2 > 0) {
580 for (i = 0; i < axid->bufnum2; i++) {
581 scfg->afBuffer[i] =
582 (uint32_t)(regptr->paddr);
583 regptr++;
584 }
585 }
586
587 vfe_stats_config(scfg);
588 }
589 break;
590
591 case CMD_STATS_AF_AXI_CFG: {
592 }
593 break;
594
595 case CMD_FRAME_BUF_RELEASE: {
596
597 struct msm_frame *b;
598 unsigned long p;
599 struct vfe_cmd_output_ack fack;
600
601 if (!data)
602 return -EFAULT;
603
604 b = (struct msm_frame *)(cmd->value);
605 p = *(unsigned long *)data;
606
607 b->path = MSM_FRAME_ENC;
608
609 fack.ybufaddr[0] =
610 (uint32_t)(p + b->y_off);
611
612 fack.chromabufaddr[0] =
613 (uint32_t)(p + b->cbcr_off);
614
615 if (b->path == MSM_FRAME_PREV_1)
616 vfe_output1_ack(&fack);
617
618 if (b->path == MSM_FRAME_ENC ||
619 b->path == MSM_FRAME_PREV_2)
620 vfe_output2_ack(&fack);
621 }
622 break;
623
624 case CMD_SNAP_BUF_RELEASE: {
625 }
626 break;
627
628 case CMD_STATS_BUF_RELEASE: {
629 struct vfe_cmd_stats_wb_exp_ack sack;
630
631 if (!data)
632 return -EFAULT;
633
634 sack.nextWbExpOutputBufferAddr = *(uint32_t *)data;
635 vfe_stats_wb_exp_ack(&sack);
636 }
637 break;
638
639 case CMD_AXI_CFG_OUT1: {
640 struct axidata *axid;
641
642 axid = data;
643 if (!axid)
644 return -EFAULT;
645
646 axio =
647 kmalloc(sizeof(struct vfe_cmd_axi_output_config),
648 GFP_ATOMIC);
649 if (!axio)
650 return -ENOMEM;
651
652 if (copy_from_user(axio, (void __user *)(vfecmd.value),
653 sizeof(struct vfe_cmd_axi_output_config))) {
654 kfree(axio);
655 return -EFAULT;
656 }
657
658 vfe_config_axi(OUTPUT_1, axid, axio);
659 vfe_axi_output_config(axio);
660 }
661 break;
662
663 case CMD_AXI_CFG_OUT2:
664 case CMD_RAW_PICT_AXI_CFG: {
665 struct axidata *axid;
666
667 axid = data;
668 if (!axid)
669 return -EFAULT;
670
671 axio =
672 kmalloc(sizeof(struct vfe_cmd_axi_output_config),
673 GFP_ATOMIC);
674 if (!axio)
675 return -ENOMEM;
676
677 if (copy_from_user(axio, (void __user *)(vfecmd.value),
678 sizeof(struct vfe_cmd_axi_output_config))) {
679 kfree(axio);
680 return -EFAULT;
681 }
682
683 vfe_config_axi(OUTPUT_2, axid, axio);
684
685 axio->outputDataSize = 0;
686 vfe_axi_output_config(axio);
687 }
688 break;
689
690 case CMD_AXI_CFG_SNAP_O1_AND_O2: {
691 struct axidata *axid;
692 axid = data;
693 if (!axid)
694 return -EFAULT;
695
696 axio =
697 kmalloc(sizeof(struct vfe_cmd_axi_output_config),
698 GFP_ATOMIC);
699 if (!axio)
700 return -ENOMEM;
701
702 if (copy_from_user(axio, (void __user *)(vfecmd.value),
703 sizeof(struct vfe_cmd_axi_output_config))) {
704 kfree(axio);
705 return -EFAULT;
706 }
707
708 vfe_config_axi(OUTPUT_1_AND_2,
709 axid, axio);
710 vfe_axi_output_config(axio);
711 cmd_data = axio;
712 }
713 break;
714
715 default:
716 break;
717 }
718
719 kfree(scfg);
720
721 kfree(axio);
722
723
724
725
726
727
728
729
730
731 return rc;
732}
733
734static int vfe_init(struct msm_vfe_callback *presp,
735 struct platform_device *dev)
736{
737 int rc = 0;
738
739 rc = vfe_cmd_init(presp, dev, vfe_syncdata);
740 if (rc < 0)
741 return rc;
742
743
744 return msm_camio_enable(dev);
745}
746
747void msm_camvfe_fn_init(struct msm_camvfe_fn *fptr, void *data)
748{
749 mutex_init(&vfe_lock);
750 fptr->vfe_init = vfe_init;
751 fptr->vfe_enable = vfe_enable;
752 fptr->vfe_config = vfe_config;
753 fptr->vfe_disable = vfe_disable;
754 fptr->vfe_release = vfe_release;
755 vfe_syncdata = data;
756}
757