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